home *** CD-ROM | disk | FTP | other *** search
/ Future Workshop / Future Workshop.iso / multimed / qtw111 / mplayer / moviewnd.c < prev    next >
C/C++ Source or Header  |  1994-01-11  |  138KB  |  3,384 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // MovieWnd.c - Movie Player - QuickTime for Windows
  5. //
  6. //              Version 1.0
  7. //
  8. //              (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13.  
  14. // Includes
  15. // --------
  16. #include <Windows.H>   // Required by Windows
  17. #include <commdlg.h>   // Required for PRINTDLG struct
  18. #include <stdio.h>     // Required for sprintf routine
  19. #include <sys\types.h> // Required for stat.h
  20. #include <sys\stat.h>  // Required for _stat routine
  21. #include <math.h>      // Required for abs()
  22. #include <string.h>    // Required for memset
  23.  
  24. #include <qtw.h>   // Interface to QuickTime
  25. #include <qtole.h> // Interface to qtole dll
  26.  
  27. #include "common.h" // Interface to common.c
  28.  
  29. #include "player.h"  // Interface to other *.c files
  30. #include "player.hr" // Defines used in *.rc files
  31.  
  32.  
  33. // Constants
  34. // ---------
  35. #define GETINFOMOVIEPROP      "Movie"
  36.  
  37.  
  38. // Message-Persistent Data
  39. // -----------------------
  40. static struct // Hungarian notation: g
  41.   {WORD        wMovieCount;            // Used during enumeration for
  42.                                        // duplication checking
  43.    BOOL        bCreating;              //   "    "       "
  44.    HWND        hwndFirstDup;           //   "    "       "
  45.    WORD        wMovieControllerHeight; // Height of movie controller
  46.    BOOL        bUpdatingInfo;          // Updating info dialog flag
  47.    char        szSelectFormat[30];     // Info dialog selection format string
  48.    char        szNoSelection[20];      // Info dialog "no selection" string
  49.    HICON       hmovieIcon;             // Movie frame icon
  50.    HCURSOR     hcursor;                // Current cursor. We need to set cursor
  51.                                        // during constrained resizing so class
  52.                                        // cursor must be set to NULL;
  53.    RECT        rcResizeRect;           // Rect used during constrained resizing
  54.    POINT       ptCursorOffset;         // Offset of cursor from edge of wnd rect
  55.    WORD        wSides;                 // Combined width of vertical size borders
  56.    WORD        wTBBorder;              // Combined width of horizontal size borders
  57.    WORD        wTopAndBottom;          // Difference in height between movie and
  58.                                        // movie window. This includes the movie
  59.                                        // controller
  60.    WORD        wSoundOnlyDefWidth;     // Default width of a sound only movie
  61.    WORD        wScaleWidth;            // Scale width used in constrained resize
  62.    WORD        wScaleHeight;           // Scale height used in constrained resize
  63.    BOOL        bFatResizeBorder;       // Flag that causes resize border to be
  64.                                        // drawn 2 pixels thicker
  65.    WNDPROC     lpOldGBProc;            // Original grow box proc
  66.    WNDPROC     lpNewGBProc;            // Subclassed grow box proc
  67.    HWND        hwndMaximizedMovie;     // Handle of maximized movie wnd
  68.    BOOL        bCapturedGrowBox;       // TRUE if the grow box input has
  69.                                        // been captured
  70.   } g;
  71.  
  72. // Macros
  73. // ----------------------
  74. #define ISKEYDOWN( vKey )  (GetKeyState( (int) (vKey) ) < 0 )
  75.  
  76.  
  77. // Exported callback functions
  78. // ----------------------------
  79. BOOL __export CALLBACK GetInfoDlgProc       (HWND, UINT, WPARAM, LPARAM);
  80. BOOL __export CALLBACK CheckDupEnumProc     (HWND, LPARAM);
  81.  
  82. BOOL __export CALLBACK ActionFilter   (MovieController, UINT, LPVOID, LONG);
  83.  
  84. BOOL __export CALLBACK MovieChildEnumProc   (HWND, LPARAM);
  85. LONG __export CALLBACK GBSubClassProc       (HWND, UINT, WPARAM, LPARAM);
  86.  
  87. // Internal Function Declarations
  88. // ------------------------------
  89. static LONG   NEAR PlayerMovieCreate        (HWND, LPARAM );
  90. static LONG   NEAR PlayerEditCommands       (HWND, WPARAM, WORD);
  91. static LONG   NEAR PlayerMovieCommands      (HWND, WPARAM, WORD);
  92. static LONG   NEAR PrintFrame               (HWND, LPPRINTDLG);
  93. static VOID   NEAR FillMovieInfo            (HWND, NPMOVIEDATA);
  94. static LONG   NEAR StartTheMovie            (NPMOVIEDATA);
  95. static LONG   NEAR StopTheMovie             (NPMOVIEDATA);
  96. static VOID   NEAR UpdateInfoFileName       (NPMOVIEDATA);
  97. static VOID   NEAR DisplayCurrentSelection  (NPMOVIEDATA);
  98. static LONG   NEAR ResizeMovieAndWindow     (HWND, BOOL, NPMOVIEDATA, WORD, WORD);
  99. static LONG   NEAR ResizeMovie              (NPMOVIEDATA, WORD, WORD);
  100. static LONG   NEAR InitializePopupMenus     (HWND, HMENU, int);
  101. static LONG   NEAR SetMinMaxInfo            (HWND, NPMOVIEDATA, MINMAXINFO FAR *);
  102. static VOID   NEAR ActivateTheController    (HWND, NPMOVIEDATA, BOOL);
  103. static LONG   NEAR PaintTheIcon             (HWND, NPMOVIEDATA);
  104. static HFONT  NEAR MakeAnArialFont          (HDC, int);
  105. static VOID   NEAR UpdateGBBoundsRect       (HWND, NPMOVIEDATA);
  106. static WORD   NEAR InitializeResize         (HWND, NPMOVIEDATA, WORD, POINT);
  107. static VOID   NEAR DrawTheFrameRect         (LPRECT, BOOL);
  108. static VOID   NEAR MoveTheMovieResizeRect   (HWND, NPMOVIEDATA,
  109.                                                           WORD, POINT, BOOL);
  110. static VOID   NEAR GetProportionalDimensions (NPMOVIEDATA, PWORD, PWORD, BOOL);
  111. static VOID   NEAR AdjustForMinProportionalSize(HWND, NPMOVIEDATA,
  112.                                                       LPWORD, LPWORD, BOOL);
  113. static BOOL   NEAR IsNormalSize             (LPRECT, NPMOVIEDATA);
  114. static BOOL   NEAR SubclassTheGrowBox       (HWND, NPMOVIEDATA);
  115. static BOOL   NEAR InitMaxWndGrowBoxResize  (HWND, POINT);
  116. static VOID   NEAR MoveTheFrameResizeRect   (HWND, POINT);
  117. static LONG   NEAR FixUpMovieTiling         (HWND, NPMOVIEDATA, LPWINDOWPOS);
  118. static VOID   NEAR SetOptionsDefaults       (HWND, NPMOVIEDATA);
  119. static VOID   NEAR PopulateOptionsStruct    (HWND, NPMOVIEDATA);
  120.  
  121.  
  122. // Function: PlayerMovieWndProc - Player Movie Window Procedure
  123. // --------------------------------------------------------------------
  124. // Parameters: As required by Microsoft Windows
  125. //
  126. // Returns:    Via DefMDIChildProc
  127. // --------------------------------------------------------------------
  128. LONG __export CALLBACK PlayerMovieWndProc
  129.     (HWND hwndMovie, UINT message, WPARAM wParam, LPARAM lParam)
  130.  
  131. {
  132.     NPMOVIEDATA      pMovieData;      // Temp -> to movie data struct
  133.     HMOVIEDATA       hMovieData;      // Temp handle of movie data
  134.     WNDENUMPROC      lpfnEnumMovies;  // -> enumeration proc
  135.     NPMOVIEDATA      pFirstMovieData; // Temp -> to movie data struct
  136.                                       // used during duplication processing
  137.     WORD             wMovieWidth;     // Movie normal width
  138.     WORD             wMovieHeight;    // Movie normal height
  139.     WORD             wWidth;          // Window width
  140.     WORD             wHeight;         // Window height
  141.     LRESULT          lRetVal;         // Return from DefMDIChildProc
  142.     POINT            ptCursor;        // Cursor position in screen coords.
  143.     LPQTOLE_OLEDATA  lpOleData;       // -> ole data
  144.  
  145.     static WORD      wResizeHitTestCode; // Equals the NC hit test code when
  146.                                          // resizing with SHIFT or CONTROL
  147.  
  148.  
  149.     pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 );
  150.     if( pMovieData &&
  151.         MCIsPlayerMessage( pMovieData->mcMovieController,
  152.         hwndMovie, message, wParam, lParam ))
  153.         return DefMDIChildProc( hwndMovie, message, wParam, lParam );
  154.  
  155.     switch( message ) {
  156.         case WM_CREATE:
  157.             // Load movie frame icon used by all instances
  158.             if( !g.hmovieIcon )
  159.                 g.hmovieIcon = LoadIcon( PlayerQueryResources(),
  160.                 MAKEINTRESOURCE( PLAYER_MOVIE_ICON ));
  161.             if( !g.hcursor )
  162.                 g.hcursor = LoadCursor( NULL, IDC_ARROW );
  163.  
  164.             return PlayerMovieCreate( hwndMovie, lParam );
  165.  
  166.         case WM_SIZE:
  167.             if( !pMovieData )
  168.                 break; // break to DefMDIChildProc
  169.  
  170.             wMovieWidth  = LOWORD( lParam );
  171.             if( HIWORD( lParam ) > g.wMovieControllerHeight )
  172.                 wMovieHeight = HIWORD( lParam ) - g.wMovieControllerHeight;
  173.             else
  174.                 wMovieHeight = 0;
  175.  
  176.             if( wParam ) // Minimizing, maximizing, etc
  177.             {
  178.                 if( wParam == SIZE_MAXIMIZED )
  179.                 // If subclass failed, remove grow box
  180.                 {
  181.                     if( IsZoomed( PlayerQueryFrameWindow()) ||
  182.                         !pMovieData->bGrowBoxSubclassed ) {
  183.                         SetRectEmpty( &pMovieData->rcGrowBox );
  184.                         MCDoAction( pMovieData->mcMovieController,
  185.                             mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  186.                     }
  187.                     else if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ) { // Reset grow box bounds rect
  188.                         UpdateGBBoundsRect( hwndMovie, pMovieData );
  189.                     }
  190.  
  191.                     if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED )
  192.                         StartTheMovie( pMovieData );
  193.  
  194.                     g.hwndMaximizedMovie = hwndMovie;
  195.                     ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  196.                 }
  197.                 else if( wParam == SIZE_MINIMIZED ) {
  198.                     SetRectEmpty( &pMovieData->rcGrowBox );
  199.                     MCDoAction( pMovieData->mcMovieController,
  200.                         mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  201.  
  202.                     StopTheMovie( pMovieData );
  203.  
  204.                     PaintTheIcon( hwndMovie, pMovieData );
  205.                 }
  206.  
  207.                 pMovieData->wMinMaxEtc = wParam;
  208.             }
  209.             else if( pMovieData->wMinMaxEtc ) // restoring
  210.             { // Reset grow box bounds rect
  211.                 UpdateGBBoundsRect( hwndMovie, pMovieData );
  212.  
  213.                 if( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) {
  214.                     if( g.hwndMaximizedMovie == hwndMovie )
  215.                         g.hwndMaximizedMovie = NULL;
  216.  
  217.                     ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  218.                 }
  219.                 else if( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ) {
  220.                     StartTheMovie( pMovieData );
  221.                 }
  222.                 pMovieData->wMinMaxEtc = 0;
  223.             }
  224.             else if( pMovieData->bDisableSizeMsgProcessing ) { // Already processing create message, menu item or resizing
  225.                                                                // to aspect ratio or even multiple of pixels according
  226.                                                                // to key states in the last else under this message
  227.                 pMovieData->bDisableSizeMsgProcessing = FALSE;
  228.             }
  229.             else {
  230.                 ResizeMovie( pMovieData, wMovieWidth, wMovieHeight);
  231.             }
  232.  
  233.             // Need this for movie controller to repaint correctly
  234.             // when window is small
  235.             if( wResizeHitTestCode ||
  236.                 ( PlayerQueryMDIAction() == PLAYER_WINDOW_TILE ))
  237.                 InvalidateRect( hwndMovie, NULL, FALSE );
  238.  
  239.             break; // break to DefMDIChildProc
  240.  
  241.         case WM_MOVE:
  242.             if( !pMovieData ||
  243.                 ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  244.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  245.                 break; // break to DefMDIChildProc
  246.  
  247.             // Need to reset grow box bounds rect after a move because it is
  248.             // the client rect of the MDI frame window expressed in the client
  249.             // coordinates of the movie window
  250.             UpdateGBBoundsRect( hwndMovie, pMovieData );
  251.  
  252.             break; // break to DefMDIChildProc
  253.  
  254.         case WM_WINDOWPOSCHANGING:
  255.             if( pMovieData &&
  256.                 ( PlayerQueryMDIAction() == PLAYER_WINDOW_TILE )) {
  257.                 FixUpMovieTiling( hwndMovie,
  258.                     pMovieData, (LPWINDOWPOS) lParam );
  259.             }
  260.  
  261.             break; // break to DefMDIChildProc
  262.  
  263.         case WM_COMMAND:
  264.             switch( wParam ) {
  265.                 case PLAYER_EDIT_COPY: // edit menu popup
  266.                 case PLAYER_EDIT_OPTIONS:
  267.                 case PLAYER_EDIT_CANCELSEL:
  268.                     return PlayerEditCommands
  269.                         ( hwndMovie, wParam, HIWORD( lParam ));
  270.  
  271.                 case PLAYER_MOVIE_GETINFO: // movie menu popup
  272.                 case PLAYER_MOVIE_STOPATEND:
  273.                 case PLAYER_MOVIE_LOOP:
  274.                 case PLAYER_MOVIE_BACKANDFORTH:
  275.                 case PLAYER_MOVIE_PLAYSELONLY:
  276.                 case PLAYER_MOVIE_HALFSIZE:
  277.                 case PLAYER_MOVIE_NORMALSIZE:
  278.                 case PLAYER_MOVIE_DOUBLESIZE:
  279.                 case PLAYER_MOVIE_SHOWPOSTER:
  280.                     return PlayerMovieCommands
  281.                         ( hwndMovie, wParam, HIWORD( lParam ));
  282.  
  283.                 default:
  284.                     break; // break to DefMDIChildProc
  285.             }
  286.  
  287.             break;
  288.  
  289.         // WM_USER messages
  290.  
  291.         case WM_PLAYER_PRINTFRAME:
  292.             return PrintFrame( hwndMovie, (LPPRINTDLG) lParam );
  293.  
  294.         case WM_PLAYER_INITPOPUPS:
  295.             return InitializePopupMenus
  296.                 ( hwndMovie, (HMENU) wParam, (int) LOWORD(lParam) );
  297.  
  298.         case WM_PLAYER_ACTIVATEMOVIE:
  299.             if( pMovieData ) {
  300.                 SetMovieActive( pMovieData->mMovie, TRUE );
  301.                 SetFocus( hwndMovie );
  302.             }
  303.  
  304.             return 0L;
  305.  
  306.         case WM_PLAYER_ACTIVATECONTROLLER:
  307.             if( pMovieData && pMovieData->mcMovieController )
  308.                 ActivateTheController( hwndMovie, pMovieData, TRUE );
  309.  
  310.             return 0L;
  311.  
  312.         case WM_PLAYER_PLAYTHEMOVIE: // Send by frame window when it is
  313.                                      // iconized or restored
  314.             if( pMovieData &&
  315.                 ( pMovieData->wMinMaxEtc != SIZE_MINIMIZED )) {
  316.                 if( (BOOL) wParam )
  317.                     StartTheMovie( pMovieData );
  318.                 else
  319.                     StopTheMovie( pMovieData );
  320.             }
  321.  
  322.             return 0L;
  323.  
  324.         case WM_PLAYER_UPDATEGBBOUNDSRECT:
  325.             // Frame window sends this message when size changes
  326.             if( !pMovieData ||
  327.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  328.                 return 0L;
  329.  
  330.             UpdateGBBoundsRect( hwndMovie, pMovieData );
  331.  
  332.             return 0L;
  333.  
  334.         // end WM_USER messages
  335.  
  336.         case WM_NCACTIVATE:
  337.             if( pMovieData && pMovieData->mcMovieController ) { // Activate or deactivate the controller
  338.                 if( (BOOL) wParam ) { // Post message to introduce a delay so that
  339.                                       // activation occurs after mouse click.
  340.                                       // Activate is called directly if PostMessage fails
  341.                     if( !PostMessage( hwndMovie,
  342.                         WM_PLAYER_ACTIVATECONTROLLER, TRUE, 0L ))
  343.                         ActivateTheController( hwndMovie, pMovieData, TRUE );
  344.                 }
  345.                 else {
  346.                     ActivateTheController( hwndMovie, pMovieData, FALSE );
  347.                 }
  348.             }
  349.  
  350.             break; // break to DefMDIChildProc
  351.  
  352.         case WM_GETMINMAXINFO:
  353.             SetMinMaxInfo( hwndMovie, pMovieData, (MINMAXINFO FAR*) lParam );
  354.             break; // break to DefMDIChildProc
  355.  
  356.         case WM_QUERYDRAGICON:
  357.             return MAKELONG( g.hmovieIcon, 0 );
  358.  
  359.         case WM_NCHITTEST:
  360.             lRetVal =  DefMDIChildProc
  361.                 ( hwndMovie, message, wParam, lParam );
  362.             if( pMovieData && pMovieData->bSoundOnly ) {
  363.                 switch( LOWORD( lRetVal )) {
  364.                     case HTTOP:
  365.                     case HTBOTTOM:
  366.                         return 0L;
  367.  
  368.                     case HTTOPLEFT:
  369.                     case HTBOTTOMLEFT:
  370.                         return HTLEFT;
  371.  
  372.                     case HTTOPRIGHT:
  373.                     case HTBOTTOMRIGHT:
  374.                         return HTRIGHT;
  375.  
  376.                     default:
  377.                         return lRetVal;
  378.                 }
  379.             }
  380.             else
  381.                 return lRetVal;
  382.  
  383.         case WM_NCLBUTTONDOWN: // We must do all border drag resizing
  384.                                // so we can do the constrained resizing
  385.             if( pMovieData &&
  386.                 ( wResizeHitTestCode = InitializeResize
  387.                 ( hwndMovie, pMovieData, wParam, MAKEPOINT( lParam )))) {
  388.                 SetCapture( hwndMovie );
  389.                 MoveTheMovieResizeRect( hwndMovie, pMovieData,
  390.                     wResizeHitTestCode, MAKEPOINT( lParam ), TRUE );
  391.                 return 0L;
  392.             }
  393.  
  394.             break; // break to DefMDIChildProc
  395.  
  396.         case WM_MOUSEMOVE:
  397.             if( wResizeHitTestCode ) {
  398.                 ptCursor = MAKEPOINT( lParam );
  399.                 ClientToScreen( hwndMovie, &ptCursor );
  400.                 MoveTheMovieResizeRect( hwndMovie, pMovieData,
  401.                     wResizeHitTestCode, ptCursor, FALSE );
  402.             }
  403.             else if( g.bCapturedGrowBox ) // This move is initiated in the
  404.                                           // grow box subclass proc.
  405.             {
  406.                 ptCursor = MAKEPOINT( lParam );
  407.                 ClientToScreen( hwndMovie, &ptCursor );
  408.                 MoveTheFrameResizeRect( hwndMovie, ptCursor );
  409.             }
  410.  
  411.             SetCursor( g.hcursor );
  412.             return 0L;
  413.  
  414.         case WM_LBUTTONUP:
  415.             if( wResizeHitTestCode ) {
  416.                 DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  417.  
  418.                 ReleaseCapture();
  419.                 DrawTheFrameRect( NULL, FALSE ); // This cleans up
  420.                 ClipCursor( NULL );
  421.                 g.hcursor = LoadCursor( NULL, IDC_ARROW );
  422.  
  423.                 if( !pMovieData->bSoundOnly &&
  424.                     ( ISKEYDOWN( VK_CONTROL ) || ISKEYDOWN( VK_SHIFT ))) {
  425.                     wWidth  = g.rcResizeRect.right - g.rcResizeRect.left;
  426.                     wHeight = g.rcResizeRect.bottom - g.rcResizeRect.top;
  427.  
  428.                     AdjustForMinProportionalSize
  429.                         ( hwndMovie, pMovieData,
  430.                         &wWidth, &wHeight, ISKEYDOWN( VK_CONTROL ));
  431.  
  432.                     g.rcResizeRect.right  = g.rcResizeRect.left + wWidth;
  433.                     g.rcResizeRect.bottom = g.rcResizeRect.top + wHeight;
  434.                 }
  435.  
  436.                 MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  437.                     (LPPOINT) &g.rcResizeRect, 2 );
  438.  
  439.                 MoveWindow( hwndMovie,
  440.                     g.rcResizeRect.left, g.rcResizeRect.top,
  441.                     g.rcResizeRect.right - g.rcResizeRect.left,
  442.                     g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  443.  
  444.                 // This needs to be after the MoveWindow call
  445.                 wResizeHitTestCode = 0;
  446.             }
  447.             else if( g.bCapturedGrowBox ) // This move is initiated in the
  448.                                           // grow box subclass proc.
  449.             {
  450.                 g.bCapturedGrowBox = FALSE;
  451.                 DrawTheFrameRect( &g.rcResizeRect, FALSE );
  452.  
  453.                 ReleaseCapture();
  454.                 DrawTheFrameRect( NULL, FALSE ); // This cleans up
  455.                 ClipCursor( NULL );
  456.  
  457.                 MoveWindow( PlayerQueryFrameWindow(),
  458.                     g.rcResizeRect.left, g.rcResizeRect.top,
  459.                     g.rcResizeRect.right - g.rcResizeRect.left,
  460.                     g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
  461.             }
  462.  
  463.             return 0L;
  464.  
  465.         case WM_PAINT:
  466.             // We paint the icon but QTW takes care of all the painting
  467.             // otherwise.
  468.             if( pMovieData && IsIconic( hwndMovie ))
  469.                 return PaintTheIcon( hwndMovie, pMovieData );
  470.             break; // break to DefMDIChildProc
  471.  
  472.         case WM_DESTROY:
  473.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer )
  474.                 PopulateOptionsStruct( hwndMovie, pMovieData );
  475.             break; // break to DefMDIChildProc
  476.  
  477.         case WM_NCDESTROY:
  478.             if( !pMovieData )
  479.                 break;
  480.  
  481.             if( pMovieData->lpFilterProc ) {
  482.                 MCSetActionFilter
  483.                     ( pMovieData->mcMovieController, NULL, 0L );
  484.                 FreeProcInstance( (FARPROC ) pMovieData->lpFilterProc );
  485.                 pMovieData->lpFilterProc = NULL;
  486.             }
  487.  
  488.             if( pMovieData->hwndGetInfo )
  489.                 DestroyWindow( pMovieData->hwndGetInfo );
  490.  
  491.             if( pMovieData->mcMovieController )
  492.                 DisposeMovieController( pMovieData->mcMovieController );
  493.             if( pMovieData->mMovie )
  494.                 DisposeMovie( pMovieData->mMovie );
  495.  
  496.             // Last instance destroys icon and grow box subclass proc
  497.             if( PlayerQueryNumMovies() <= 1 ) {
  498.                 if( g.hmovieIcon )
  499.                     DestroyIcon( g.hmovieIcon );
  500.                 g.hmovieIcon = NULL;
  501.  
  502.                 // Free the grow box subclass proc
  503.                 if( g.lpNewGBProc ) {
  504.                     FreeProcInstance( (FARPROC) g.lpNewGBProc );
  505.                     g.lpNewGBProc = NULL;
  506.                 }
  507.                 g.lpOldGBProc = NULL;
  508.             }
  509.             else { // Check for duplicates
  510.                 g.wMovieCount  = 0;
  511.                 g.bCreating    = FALSE;
  512.                 g.hwndFirstDup = NULL;
  513.  
  514.                 if( lpfnEnumMovies = (WNDENUMPROC) MakeProcInstance
  515.                     ( (FARPROC) CheckDupEnumProc, PlayerQueryInstance())) {
  516.                     EnumChildWindows( PlayerQueryClientWindow(),
  517.                         lpfnEnumMovies, MAKELPARAM( hwndMovie, 0 ));
  518.                     FreeProcInstance( (FARPROC) lpfnEnumMovies );
  519.                 }
  520.  
  521.                 // if no dups, eliminate :1 on first
  522.                 // hwndFirstDup is set in CheckDupEnumProc
  523.                 if( ( g.wMovieCount == 1 ) && g.hwndFirstDup &&
  524.                     ( pFirstMovieData = (NPMOVIEDATA)
  525.                     GetWindowWord( g.hwndFirstDup, 0 ))) {
  526.                     pFirstMovieData->wDuplicationIndex = 0;
  527.                     SetWindowText( g.hwndFirstDup,
  528.                         pFirstMovieData->szMovieName );
  529.                 }
  530.             }
  531.  
  532.             // Tell OLE that window is closed. Movie has been disposed
  533.             // qtole.dll used hwndObject so don't null the handle in struct
  534.             pMovieData->qtoleOptions.mMovie = NULL;
  535.  
  536.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer )
  537.                 QTOLE_ClosingDocWnd( lpOleData,
  538.                 (LPQTOLE_OPTIONS) &pMovieData->qtoleOptions );
  539.  
  540.             LocalUnlock( hMovieData =
  541.                 (HMOVIEDATA) LocalHandle( pMovieData ));
  542.             LocalFree( hMovieData );
  543.             SetWindowWord( hwndMovie, 0, 0);
  544.  
  545.             // Update the movie count in the frame window globals
  546.             SendMessage( PlayerQueryFrameWindow(),
  547.                 WM_PLAYER_MOVIEDELETED, (WPARAM) hwndMovie, 0L );
  548.  
  549.             break; // break to DefMDIChildProc
  550.  
  551.     }
  552.  
  553.     return DefMDIChildProc( hwndMovie, message, wParam, lParam );
  554. }
  555.  
  556.  
  557. // Function: PlayerMovieCreate - process WM_CREATE message
  558. // --------------------------------------------------------------------
  559. // Parameters: HWND        hwndMovie;      Handle of movie window
  560. //             LPARAM      lParam;         lParam of WM_CREATE message
  561. //
  562. // Returns:    0 if OK, else returns -1 to kill app
  563. // --------------------------------------------------------------------
  564. static LONG NEAR PlayerMovieCreate( HWND hwndMovie, LPARAM lParam )
  565.  
  566. {
  567.     NPMOVIEDATA        pMovieData;             // Temp -> to movie data struct
  568.     HMOVIEDATA         hMovieData;             // Handle to movie data struct
  569.     LPMDICREATESTRUCT  lpmdicreate;            // MDI create struct
  570.     MovieFile          movMovieFile;           // Movie file handle
  571.     char               szBuffer[MAX_PATH_LEN]; // Temp buffer
  572.     struct _stat       statbuf;                // File statictics struct
  573.     WORD               wIDString;              // Resource string id
  574.     DWORD              dwBytes;                // File size
  575.     OSErr              oserr;                  // Error return
  576.     RECT               rcMovie;                // Movie rect
  577.     RECT               rcWindow;               // Window rect
  578.     RECT               rcController;           // Controller rect
  579.     POINT              ptCorner;               // Upper Left corner of movie wnd
  580.     WORD               wWidth;                 // Width of window
  581.     WORD               wHeight;                // Height of window
  582.     RECT               rcclientClient;         // Client rect of MDI client wnd
  583.     int                nDiff;                  // Temp
  584.     WNDENUMPROC        lpfnEnumMovies;         // -> to enumeration proc
  585.     LPSTR              lpName;                 // Temp -> movie name
  586.     LONG               lStyle;                 // Temp window style
  587.     UserData           udUserData;             // Handle to user data
  588.     HGLOBAL            ghMem;                  // Global mem used to get 'loop' user data
  589.     LONG               lSizeData;              // Size of 'loop' user data
  590.     LPSTR              lpUserData;             // -> 'loop' user data
  591.     int                i;                      // Loop counter
  592.     QTOLE_OPENWND      qtoleOpenWnd;           // Ole open wnd struct
  593.     LPQTOLE_OLEDATA    lpOleData;              // -> ole data
  594.     int                nLoop;
  595.  
  596.  
  597.     pMovieData = (NPMOVIEDATA) NULL;
  598.  
  599.     if( !(hMovieData = (HMOVIEDATA)
  600.         LocalAlloc( LPTR, sizeof( MOVIEDATASTRUCT )))) {
  601.         CommonTellUser( PlayerQueryResources(),
  602.             PLAYER_STRING_NOMEMORY, NULL, MB_OK );
  603.         goto Failed;
  604.     }
  605.     pMovieData = (NPMOVIEDATA) LocalLock( hMovieData );
  606.     SetWindowWord( hwndMovie, 0, (WORD) pMovieData );
  607.  
  608.     // mdi struct filled before call to MDI create in LaunchMovieWnd
  609.     lpmdicreate = (LPMDICREATESTRUCT)
  610.         ((LPCREATESTRUCT) lParam)->lpCreateParams;
  611.  
  612.     lstrcpy( pMovieData->szMoviePath, (LPSTR) lpmdicreate -> lParam );
  613.     lstrcpy( pMovieData->szMovieName, (LPSTR) lpmdicreate -> szTitle );
  614.  
  615.     // Strip off and save extension so that name fits better
  616.     // on title bar of window
  617.     pMovieData->szMovieExt[0] = '\0';
  618.     lpName = pMovieData->szMovieName;
  619.     while( *lpName ) {
  620.         if( *lpName == '.' ) {
  621.             lstrcpy( pMovieData->szMovieExt, lpName );
  622.             *lpName = '\0';
  623.             SetWindowText( hwndMovie, pMovieData->szMovieName );
  624.             break;
  625.         }
  626.         else
  627.             lpName = AnsiNext( lpName );
  628.     }
  629.  
  630.     if( ( oserr = OpenMovieFile( pMovieData->szMoviePath,
  631.         &movMovieFile, OF_READ )) == 0 ) {
  632.         oserr = NewMovieFromFile( &pMovieData->mMovie,
  633.             movMovieFile, NULL, NULL, 0, NULL );
  634.         CloseMovieFile( movMovieFile );
  635.     }
  636.  
  637.     if( oserr ) {
  638.         if( oserr == insufficientMemory )
  639.             wIDString = PLAYER_STRING_NOMEMORY;
  640.         else if( oserr == invalidDataRef )
  641.             wIDString = PLAYER_STRING_INVALIDDATAREF;
  642.         else
  643.             wIDString = PLAYER_STRING_NEWMOVIEERR;
  644.  
  645.         CommonTellUser( PlayerQueryResources(),
  646.             wIDString, PLAYER_STRING_CAPTION,
  647.             MB_OK, (LPSTR) lpmdicreate -> szTitle );
  648.         goto Failed;
  649.     }
  650.  
  651.     // Check for duplicates. Fix up titles if necessary
  652.     // Initialize globals used during enumeration
  653.     g.wMovieCount = 1;
  654.     g.bCreating =  TRUE;
  655.     if( ( PlayerQueryNumMovies() > 0 ) &&
  656.         ( lpfnEnumMovies = (WNDENUMPROC) MakeProcInstance
  657.         ( (FARPROC) CheckDupEnumProc, PlayerQueryInstance()))) {
  658.         EnumChildWindows( PlayerQueryClientWindow(),
  659.             lpfnEnumMovies, MAKELPARAM( hwndMovie, 0 ));
  660.         FreeProcInstance( (FARPROC) lpfnEnumMovies );
  661.  
  662.         // Fix up title if duplicate
  663.         // Title of 1st dup is fixed up during enum
  664.         if( g.wMovieCount > 1 ) {
  665.             pMovieData->wDuplicationIndex = g.wMovieCount;
  666.             wsprintf( szBuffer, "%s:%u",
  667.                 (LPSTR) pMovieData->szMovieName,
  668.                 pMovieData->wDuplicationIndex );
  669.             SetWindowText( hwndMovie, szBuffer );
  670.         }
  671.     }
  672.  
  673.     // file size  Note: _stat path name is in OEM char set
  674.     lstrcpy( szBuffer, pMovieData->szMoviePath );
  675.     AnsiToOem( szBuffer, szBuffer );
  676.     if( (_stat( szBuffer, &statbuf )) == 0 ) {
  677.         if( statbuf.st_size < 1000L ) {
  678.             dwBytes = (DWORD) statbuf.st_size;
  679.             wIDString = PLAYER_STRING_SIZEBYTES;
  680.         }
  681.         else {
  682.             dwBytes = (DWORD) ( statbuf.st_size / 1000L );
  683.             wIDString = PLAYER_STRING_SIZEKBYTES;
  684.         }
  685.  
  686.         LoadString( PlayerQueryResources(),
  687.             wIDString, szBuffer, sizeof( szBuffer ));
  688.         wsprintf( pMovieData->szFileSize, szBuffer, dwBytes );
  689.     }
  690.  
  691.     pMovieData->bSoundOnly = FALSE;
  692.     pMovieData->idMovieInfo.idSize = sizeof( ImageDescription );
  693.     oserr = GetVideoInfo( pMovieData->mMovie, &pMovieData->idMovieInfo );
  694.     if( oserr == noVideoTrackInMovie ) {
  695.         pMovieData->bSoundOnly = TRUE;
  696.     }
  697.     else if( oserr ) {
  698.         CommonTellUser( PlayerQueryResources(),
  699.             PLAYER_STRING_NOINFO, PLAYER_STRING_CAPTION, MB_OK );
  700.         goto Failed;
  701.     }
  702.  
  703.     pMovieData->sdSoundInfo.descSize = sizeof( SoundDescription );
  704.     pMovieData->oserrSoundInfo =
  705.         GetSoundInfo( pMovieData->mMovie, &pMovieData->sdSoundInfo );
  706.  
  707.  
  708.     // Set copy option default values
  709.     SetOptionsDefaults( hwndMovie, pMovieData );
  710.  
  711.     // Instantiate the movie controller
  712.     if( !pMovieData->bSoundOnly ) // Call only if there is video
  713.     {
  714.         GetMovieBox( pMovieData->mMovie, &rcMovie );
  715.         OffsetRect( &rcMovie, -rcMovie.left, -rcMovie.top );
  716.  
  717.         // Now resize window if default option is half or double size
  718.         if( pMovieData->qtoleOptions.bSizeHalf ) {
  719.             rcMovie.right  /= 2;
  720.             rcMovie.bottom /= 2;
  721.         }
  722.         else if( pMovieData->qtoleOptions.bSizeDouble ) {
  723.             rcMovie.right  *= 2;
  724.             rcMovie.bottom *= 2;
  725.         }
  726.     }
  727.  
  728.     // Movie with no video or no rect gets a default width to pass to
  729.     // NewMovieController
  730.     if( pMovieData->bSoundOnly || IsRectEmpty( &rcMovie )) {
  731.         rcMovie.left = rcMovie.top = 0;
  732.         rcMovie.right = 8 * GetSystemMetrics( SM_CXVSCROLL );
  733.         rcMovie.bottom = 0;
  734.     }
  735.  
  736.     if( !( pMovieData->mcMovieController =
  737.         NewMovieController( pMovieData->mMovie, &rcMovie,
  738.         mcTopLeftMovie | mcScaleMovieToFit, hwndMovie ))) {
  739.         CommonTellUser( PlayerQueryResources(),
  740.             PLAYER_STRING_NOCONTROLLER, PLAYER_STRING_CAPTION, MB_OK );
  741.         goto Failed;
  742.     }
  743.     MCDoAction( pMovieData->mcMovieController, mcActionPlay, (LPVOID) 0 );
  744.  
  745.     // Subclass the movie controller grow box for use when a
  746.     // movie window is maximized
  747.     pMovieData->bGrowBoxSubclassed =
  748.         SubclassTheGrowBox( hwndMovie, pMovieData );
  749.  
  750.     // Override loop mode depending on user data
  751.     ghMem = NULL;
  752.     nLoop = 0;
  753.     if( ( udUserData = GetMovieUserData( pMovieData->mMovie )) &&
  754.         ( CountUserDataType( udUserData,
  755.         QTFOURCC( 'L', 'O', 'O', 'P' )) > 0 )) {
  756.         pMovieData->qtoleOptions.bLoop           = TRUE;
  757.         pMovieData->qtoleOptions.bLoopPalindrome = FALSE;
  758.         if( ( ghMem = GlobalAlloc( GHND, 16L )) &&
  759.             !GetUserData( udUserData, &ghMem,
  760.             QTFOURCC( 'L', 'O', 'O', 'P' ), 1L, &lSizeData ) &&
  761.             ( lSizeData > 0L )) {
  762.             lpUserData = (LPSTR) GlobalLock( ghMem );
  763.             for( i=0; i < lSizeData; i++ ) {
  764.                 if( *lpUserData++ != '\0' ) {
  765.                     pMovieData->qtoleOptions.bLoop           = FALSE;
  766.                     pMovieData->qtoleOptions.bLoopPalindrome = TRUE;
  767.                     break;
  768.                 }
  769.             }
  770.             GlobalUnlock( ghMem );
  771.         }
  772.         if( ghMem )
  773.             GlobalFree( ghMem );
  774.     }
  775.  
  776.     // Now tell the movie controller about the loop mode
  777.     MCDoAction( pMovieData->mcMovieController, mcActionSetLooping,
  778.         (LPVOID) ( pMovieData->qtoleOptions.bLoop ||
  779.         pMovieData->qtoleOptions.bLoopPalindrome ));
  780.     MCDoAction( pMovieData->mcMovieController, mcActionSetLoopIsPalindrome,
  781.         (LPVOID) pMovieData->qtoleOptions.bLoopPalindrome );
  782.  
  783.     // Assume that the controller is attached
  784.     // Get the default UL corner of window
  785.     GetWindowRect( hwndMovie, &rcWindow );
  786.     MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  787.         (LPPOINT) &rcWindow, 2 );
  788.     ptCorner = *((LPPOINT) &rcWindow.left );
  789.  
  790.     // This includes the movie AND the moviecontroller rect
  791.     MCGetControllerBoundsRect
  792.         ( pMovieData->mcMovieController, &rcController );
  793.     rcWindow = rcController;
  794.     // At this point rcController == client rect of window
  795.  
  796.     // Save controller height
  797.     g.wMovieControllerHeight =
  798.         ( rcWindow.bottom - rcWindow.top ) -
  799.         ( rcMovie.bottom - rcMovie.top );
  800.  
  801.     // Remove maximize box if sound only movie
  802.     if( pMovieData->bSoundOnly ) {
  803.         lStyle = GetWindowLong( hwndMovie, GWL_STYLE );
  804.         lStyle &= ~WS_MAXIMIZEBOX;
  805.         SetWindowLong( hwndMovie, GWL_STYLE, lStyle );
  806.     }
  807.  
  808.     AdjustWindowRect( &rcWindow,
  809.         GetWindowLong( hwndMovie, GWL_STYLE ), FALSE );
  810.     // rcWindow now contains the size of the window
  811.  
  812.     wWidth  = rcWindow.right  - rcWindow.left;
  813.     wHeight = rcWindow.bottom - rcWindow.top;
  814.     OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  815.         ptCorner.y - rcWindow.top );
  816.     // rcWindow now contains the resized window positioned so that
  817.     // the UL corner is at the MDI default position
  818.  
  819.     // Now stash some dimensions needed later. Only need to do this once
  820.     if( pMovieData->bSoundOnly && !g.wSoundOnlyDefWidth ) {
  821.         g.wSoundOnlyDefWidth = wWidth;
  822.     }
  823.     if( !g.wSides ) {
  824.         g.wSides    = ( rcWindow.right - rcWindow.left ) -
  825.             ( rcController.right - rcController.left );
  826.         g.wTBBorder = ( rcWindow.bottom - rcWindow.top ) -
  827.             ( rcController.bottom - rcController.top );
  828.         g.wTopAndBottom = g.wMovieControllerHeight + g.wTBBorder;
  829.     }
  830.  
  831.  
  832.     // Now see if it will fit on screen.
  833.     GetClientRect( PlayerQueryClientWindow(), &rcclientClient );
  834.     if( rcWindow.right > rcclientClient.right ) { // extends beyond right border
  835.                                                   // Try to shift it to the left
  836.         nDiff = rcclientClient.right - wWidth;
  837.         rcWindow.left  = max( 0, nDiff );
  838.         rcWindow.right = rcWindow.left + wWidth;
  839.     }
  840.  
  841.     if( rcWindow.bottom > rcclientClient.bottom ) { // extends beyond bottom
  842.                                                     // Try to shift it up
  843.         nDiff = rcclientClient.bottom - wHeight;
  844.         rcWindow.top    = max( 0, nDiff );
  845.         rcWindow.bottom = rcWindow.top + wHeight;
  846.     }
  847.  
  848.     // Resize the window after disabling WM_SIZE processing
  849.     // In the unusual case that the controller is smaller than
  850.     // the smallest possible client, we stretch the controller
  851.     pMovieData->bDisableSizeMsgProcessing = TRUE;
  852.     MoveWindow( hwndMovie,
  853.         rcWindow.left, rcWindow.top, wWidth, wHeight, FALSE );
  854.  
  855.     // If movie is smaller than minimum window size, resize movie to
  856.     // fill the window
  857.     GetClientRect( hwndMovie, &rcWindow );
  858.     if( !EqualRect( &rcWindow, &rcController ))
  859.         MCSetControllerBoundsRect
  860.         ( pMovieData->mcMovieController, &rcWindow );
  861.  
  862.     // Size message turns this off, turn in on again for next
  863.     // WM_SIZE message generated by standard "create a window" processing
  864.     pMovieData->bDisableSizeMsgProcessing = TRUE;
  865.  
  866.     // Post message to activate the movie
  867.     // Post message is used to avoid a extra paint of the movie which
  868.     // causes a flash during the window creation
  869.     // SendMessage is called if PostMessage fails
  870.     if( !PostMessage( hwndMovie, WM_PLAYER_ACTIVATEMOVIE, 0, 0L ))
  871.         SendMessage( hwndMovie, WM_PLAYER_ACTIVATEMOVIE, 0, 0L );
  872.  
  873.     // Set Action filter to look for selection changes and grow box resizing.
  874.     // Do this after earlier resizing to avoid having to block filter messages
  875.     // generated during creation
  876.     if( pMovieData->lpFilterProc =
  877.         (MCActionFilter) MakeProcInstance
  878.         ( (FARPROC) ActionFilter, PlayerQueryInstance())) {
  879.         MCSetActionFilter( pMovieData->mcMovieController,
  880.             pMovieData->lpFilterProc, MAKELONG( pMovieData, hwndMovie ));
  881.     }
  882.  
  883.     // Tell qtole.dll that movie has been opened
  884.     if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer ) {
  885.         qtoleOpenWnd.lStructSize  = sizeof( qtoleOpenWnd );
  886.         qtoleOpenWnd.lVersion     = VERSION_1;
  887.         qtoleOpenWnd.wObjectType  = MOVIE_OBJECT;
  888.         qtoleOpenWnd.hwndObject   = hwndMovie;
  889.         qtoleOpenWnd.lpObjectPath = pMovieData->szMoviePath;
  890.         qtoleOpenWnd.lpObjectName = pMovieData->szMovieName;
  891.  
  892.         QTOLE_OpeningNewObjectWnd( lpOleData, &qtoleOpenWnd );
  893.     }
  894.  
  895.     return  0L;
  896.  
  897.  Failed:
  898.     SetWindowWord( hwndMovie, 0, 0 );
  899.     if( pMovieData )
  900.         LocalUnlock( hMovieData );
  901.     if( hMovieData )
  902.         LocalFree  ( hMovieData );
  903.  
  904.     return -1;
  905.  
  906. }
  907.  
  908. // Function: CheckDupEnumProc - Checks for duplicate pictures and
  909. //                              fixes up titles if there are any
  910. // --------------------------------------------------------------------
  911. // Parameters: As required by Microsoft Windows
  912. //
  913. // Returns:    Always TRUE;
  914. // --------------------------------------------------------------------
  915. BOOL __export CALLBACK CheckDupEnumProc( HWND hwnd, LPARAM lParam )
  916.  
  917. // Look for duplicate pictures. Test is on path rather than just name
  918.  
  919. {
  920.     char            szBuffer[50];     // Temp buffer
  921.     HWND            hwndActiveMovie;  // Handle of active movie wnd
  922.     NPMOVIEDATA     pMovieData;       // -> enum wnd movie data struct
  923.     NPMOVIEDATA     pActiveMovieData; // -> active wnd movie data struct
  924.  
  925.     // Skip active movie
  926.     if( ( hwndActiveMovie = (HWND) LOWORD( lParam )) == hwnd )
  927.         return TRUE;
  928.  
  929.     if( !GetClassName( hwnd, szBuffer, sizeof( szBuffer )) ||
  930.         lstrcmpi( szBuffer, PLAYER_MOVIE_CLASS ))
  931.         return TRUE;
  932.  
  933.     pMovieData = (NPMOVIEDATA) GetWindowWord( hwnd, 0 );
  934.     pActiveMovieData = (NPMOVIEDATA) GetWindowWord( hwndActiveMovie, 0 );
  935.     if( !pMovieData || !pActiveMovieData )
  936.         return TRUE;
  937.  
  938.     if( !lstrcmpi( pMovieData->szMoviePath,
  939.         pActiveMovieData->szMoviePath )) { // Found a duplicate
  940.         g.wMovieCount++;
  941.         if( g.bCreating ) {
  942.             if( pMovieData->wDuplicationIndex == 0 ) {
  943.                 pMovieData->wDuplicationIndex = 1;
  944.                 wsprintf( szBuffer, "%s:%u",
  945.                     (LPSTR) pMovieData->szMovieName,
  946.                     pMovieData->wDuplicationIndex );
  947.                 SetWindowText( hwnd, szBuffer );
  948.             }
  949.         }
  950.         else {
  951.             if( pMovieData->wDuplicationIndex >
  952.                 pActiveMovieData->wDuplicationIndex ) {
  953.                 pMovieData->wDuplicationIndex--;
  954.                 wsprintf( szBuffer, "%s:%u",
  955.                     (LPSTR) pMovieData->szMovieName,
  956.                     pMovieData->wDuplicationIndex );
  957.                 SetWindowText( hwnd, szBuffer );
  958.             }
  959.             if( pMovieData->wDuplicationIndex == 1 )
  960.                 g.hwndFirstDup = hwnd;
  961.         }
  962.  
  963.         if( pMovieData->hwndGetInfo &&
  964.             !PostMessage( pMovieData->hwndGetInfo,
  965.             WM_PLAYER_INFO_UPDATEFILENAME, 0, 0L ))
  966.             SendMessage( pMovieData->hwndGetInfo,
  967.             WM_PLAYER_INFO_UPDATEFILENAME, 0, 0L );
  968.     }
  969.  
  970.     return TRUE;
  971. }
  972.  
  973.  
  974. // Function: PlayerEditCommands - Process WM_COMMAND, Edit popup messages
  975. // --------------------------------------------------------------------
  976. // Parameters: HWND   hwndMovie;      Handle of movie window
  977. //             WORD   wIDItem;        Menu or control id
  978. //             WORD   wNotifyCode;    notification message
  979. //
  980. // Returns:    LONG   generally 0L
  981. // --------------------------------------------------------------------
  982. static LONG NEAR PlayerEditCommands
  983.                     (HWND hwndMovie, WPARAM wIDItem, WORD wNotifyCode )
  984.  
  985. {
  986.     NPMOVIEDATA      pMovieData;     // -> movie data struct
  987.     TimeRecord       trZeroTime;     // Zero time
  988.     PicHandle        phFrame;        // Pic handle of copied frame
  989.     DIBHandle        hbmpDIB;        // Handle of DIB bitmap passed to clipboard
  990.     OSErr            oserr;          // Errror return value
  991.     WORD             wIDString;      // ID of error string
  992.     HDC              hdc;            // Device context of window
  993.     HDC              hdcMem;         // Memory dc
  994.     ImageDescription idPicInfo;      // Image description struct
  995.     HBITMAP          hbmpCompatible; // Mem bitmap
  996.     HBITMAP          hbmpSave;       // Prev bitmap
  997.     RECT             rcFrame;        // Rect of frame being copied
  998.     TimeRecord       trMovieTime;    // Temp time record
  999.     HPALETTE         hpal;           // Palette handle
  1000.     LPQTOLE_OLEDATA  lpOleData;      // -> ole data
  1001.  
  1002.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1003.         CommonTellUser( PlayerQueryResources(),
  1004.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1005.         return 0L;
  1006.     }
  1007.  
  1008.     switch( wIDItem ) {
  1009.         case PLAYER_EDIT_COPY:
  1010.             if( IsIconic( hwndMovie ))
  1011.                 return 0L;
  1012.  
  1013.             // If ole, let ole do the copy
  1014.             if( ( lpOleData = PlayerQueryOleData()) && lpOleData->lpqtoleServer ) {
  1015.                 PopulateOptionsStruct( hwndMovie, pMovieData );
  1016.  
  1017.                 QTOLE_Copy( lpOleData, (LPQTOLE_OPTIONS) &pMovieData->qtoleOptions );
  1018.  
  1019.                 // We must compensate for an error in certain drivers by
  1020.                 // resetting the palette back the way we found it
  1021.                 MCDoAction( pMovieData->mcMovieController,
  1022.                     mcActionSetFlags, (LPVOID) mcFlagsUseWindowPalette );
  1023.             }
  1024.             else // No ole so do copy here
  1025.             {
  1026.                 hdcMem = NULL;
  1027.                 hbmpCompatible = NULL;
  1028.                 hbmpSave = NULL;
  1029.                 phFrame  = NULL;
  1030.  
  1031.                 if( !( hdc = GetDC( hwndMovie )) ||
  1032.                     !( hdcMem = CreateCompatibleDC( hdc )) ||
  1033.                     !( phFrame = GetMoviePict( pMovieData->mMovie,
  1034.                     GetMovieTime( pMovieData->mMovie, &trMovieTime )))) {
  1035.                     wIDString = PLAYER_STRING_COPYFAILED;
  1036.                     goto CopyFailed;
  1037.                 }
  1038.  
  1039.                 if( oserr = GetPictureInfo( phFrame, &idPicInfo )) {
  1040.                     wIDString = PLAYER_STRING_COPYFAILED;
  1041.                     goto CopyFailed;
  1042.                 }
  1043.  
  1044.                 if( !( hbmpCompatible = CreateCompatibleBitmap( hdc,
  1045.                     idPicInfo.width, idPicInfo.height ))) {
  1046.                     wIDString = PLAYER_STRING_NOMEMORY;
  1047.                     goto CopyFailed;
  1048.                 }
  1049.  
  1050.                 if( !( hbmpSave = SelectObject( hdcMem, hbmpCompatible ))) {
  1051.                     wIDString = PLAYER_STRING_COPYFAILED;
  1052.                     goto CopyFailed;
  1053.                 }
  1054.  
  1055.                 rcFrame.left = rcFrame.top = 0;
  1056.                 rcFrame.right  = idPicInfo.width;
  1057.                 rcFrame.bottom = idPicInfo.height;
  1058.  
  1059.                 if( oserr = DrawPicture( hdcMem, phFrame, &rcFrame, NULL )) {
  1060.                     wIDString = PLAYER_STRING_COPYFAILED;
  1061.                     goto CopyFailed;
  1062.                 }
  1063.                 SelectObject( hdcMem, hbmpSave );
  1064.                 hbmpSave = NULL;
  1065.                 DeleteDC( hdcMem );
  1066.                 hdcMem = NULL;
  1067.  
  1068.                 OpenClipboard( hwndMovie );
  1069.                 EmptyClipboard();
  1070.                 if( !SetClipboardData( CF_BITMAP, hbmpCompatible )) {
  1071.                     wIDString = PLAYER_STRING_COPYFAILED;
  1072.                     goto CopyFailed;
  1073.                 }
  1074.                 hbmpCompatible = NULL; // Now belongs to clipboard
  1075.  
  1076.                 // Now add palette if movie has a palette
  1077.                 if( ( hpal = GetPicturePalette( phFrame )) &&
  1078.                     !SetClipboardData( CF_PALETTE, hpal ))
  1079.                     DeleteObject( hpal );
  1080.                 hpal = NULL;
  1081.  
  1082.                 // Now try to add DIBitmap to clipboard
  1083.                 if( ( hbmpDIB = PictureToDIB( phFrame )) &&
  1084.                     !SetClipboardData( CF_DIB, hbmpDIB ))
  1085.                     GlobalFree( hbmpDIB );
  1086.                 hbmpDIB = NULL;
  1087.  
  1088.                 CloseClipboard();
  1089.                 if( phFrame )
  1090.                     DisposePicture( phFrame );
  1091.                 ReleaseDC( hwndMovie, hdc );
  1092.  
  1093.                 return 0L;
  1094.  
  1095.  CopyFailed:
  1096.                 CommonTellUser( PlayerQueryResources(),
  1097.                     wIDString, PLAYER_STRING_CAPTION, MB_OK );
  1098.                 if( hbmpSave )
  1099.                     SelectObject( hdcMem, hbmpSave );
  1100.                 if( hdc )
  1101.                     ReleaseDC( hwndMovie, hdc );
  1102.                 if( hdcMem )
  1103.                     DeleteDC( hdcMem );
  1104.                 if( hbmpCompatible )
  1105.                     DeleteObject( hbmpCompatible );
  1106.                 if( phFrame )
  1107.                     DisposePicture( phFrame );
  1108.                 if( hbmpDIB )
  1109.                     GlobalFree( hbmpDIB );
  1110.             }
  1111.  
  1112.             return 0L;
  1113.  
  1114.         case PLAYER_EDIT_OPTIONS:
  1115.             PopulateOptionsStruct( hwndMovie, pMovieData );
  1116.  
  1117.             if( PlayerGetOptions( hwndMovie, &pMovieData->qtoleOptions ))
  1118.                 UpdateMovieForOptions( hwndMovie, pMovieData, FALSE );
  1119.  
  1120.             return 0L;
  1121.  
  1122.         case PLAYER_EDIT_CANCELSEL:
  1123.             trZeroTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  1124.             trZeroTime.value.dwHi = 0L;
  1125.  
  1126.             trZeroTime.value.dwLo = (DWORD) -1L;
  1127.             trZeroTime.base       = TIMEBASE_DEFAULT;
  1128.             // Set beginning of selection to zero
  1129.             MCDoAction( pMovieData->mcMovieController,
  1130.                 mcActionSetSelectionBegin, (LPVOID) &trZeroTime );
  1131.             // Set duration to zero
  1132.             trZeroTime.value.dwLo = 0L;
  1133.             trZeroTime.base       = NULL;
  1134.             MCDoAction( pMovieData->mcMovieController,
  1135.                 mcActionSetSelectionDuration, (LPVOID) &trZeroTime );
  1136.  
  1137.             return 0L;
  1138.     }
  1139.  
  1140.     return 0L; // should never get here
  1141.  
  1142. }
  1143.  
  1144.  
  1145. // Function: PlayerMovieCommands - Process WM_COMMAND, Movie popup messages
  1146. // --------------------------------------------------------------------
  1147. // Parameters: HWND          hwndMovie;      Handle of movie window
  1148. //             WORD          wIDItem;        Menu or control id
  1149. //             WORD          wNotifyCode;    notification message
  1150. //
  1151. // Returns:    LONG   generally 0L
  1152. // --------------------------------------------------------------------
  1153. static LONG NEAR PlayerMovieCommands
  1154.                   ( HWND hwndMovie, WPARAM wIDItem, WORD wNotifyCode )
  1155.  
  1156. {
  1157.     NPMOVIEDATA   pMovieData;         // -> movie data struct
  1158.     DLGPROC       lpDlgProc;          // -> info dialog proc function
  1159.     HWND          hwndInfoDialog;     // HWND of info dialog box
  1160.     TimeRecord    trPosterTime;       // Poster time
  1161.     BOOL          bPlaySelectionOnly; // Flag
  1162.  
  1163.  
  1164.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1165.         CommonTellUser( PlayerQueryResources(),
  1166.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1167.         return 0L;
  1168.     }
  1169.  
  1170.     switch( wIDItem ) {
  1171.         case PLAYER_MOVIE_GETINFO:
  1172.             if( pMovieData->hwndGetInfo )
  1173.                 SetFocus( pMovieData->hwndGetInfo );
  1174.             else if( !(lpDlgProc = (DLGPROC) MakeProcInstance
  1175.                 ( (FARPROC) GetInfoDlgProc, PlayerQueryInstance())) ||
  1176.                 !(hwndInfoDialog =
  1177.                 CreateDialog( PlayerQueryResources(),
  1178.                 MAKEINTRESOURCE( PLAYER_DLG_GETINFO ),
  1179.                 PlayerQueryFrameWindow(), lpDlgProc ))) {
  1180.                 CommonTellUser( PlayerQueryResources(),
  1181.                     PLAYER_STRING_NOMEMORY, NULL, MB_OK );
  1182.             }
  1183.  
  1184.             return 0L;
  1185.  
  1186.         case PLAYER_MOVIE_STOPATEND:
  1187.             MCDoAction( pMovieData->mcMovieController,
  1188.                 mcActionSetLoopIsPalindrome, (LPVOID) FALSE );
  1189.             MCDoAction( pMovieData->mcMovieController,
  1190.                 mcActionSetLooping, (LPVOID) FALSE );
  1191.             return 0L;
  1192.  
  1193.         case PLAYER_MOVIE_LOOP:
  1194.             MCDoAction( pMovieData->mcMovieController,
  1195.                 mcActionSetLooping, (LPVOID) TRUE );
  1196.             MCDoAction( pMovieData->mcMovieController,
  1197.                 mcActionSetLoopIsPalindrome, (LPVOID) FALSE );
  1198.             return 0L;
  1199.  
  1200.         case PLAYER_MOVIE_BACKANDFORTH:
  1201.             MCDoAction( pMovieData->mcMovieController,
  1202.                 mcActionSetLooping, (LPVOID) TRUE );
  1203.             MCDoAction( pMovieData->mcMovieController,
  1204.                 mcActionSetLoopIsPalindrome, (LPVOID) TRUE );
  1205.             return 0L;
  1206.  
  1207.         case PLAYER_MOVIE_PLAYSELONLY:
  1208.             MCDoAction( pMovieData->mcMovieController,
  1209.                 mcActionGetPlaySelection,
  1210.                 (LPVOID) &bPlaySelectionOnly );
  1211.  
  1212.             MCDoAction( pMovieData->mcMovieController,
  1213.                 mcActionSetPlaySelection,
  1214.                 (LPVOID) !bPlaySelectionOnly );
  1215.             return 0L;
  1216.  
  1217.  
  1218.         // For next 3 cases, if window is maximized or minimized, we need to
  1219.         // restore before resizing so that Windows knows that the window is
  1220.         // no longer maximized or minimized
  1221.  
  1222.         case PLAYER_MOVIE_HALFSIZE:
  1223.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1224.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1225.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1226.  
  1227.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1228.                 pMovieData->idMovieInfo.width / 2,
  1229.                 pMovieData->idMovieInfo.height / 2 );
  1230.  
  1231.         case PLAYER_MOVIE_NORMALSIZE:
  1232.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1233.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1234.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1235.  
  1236.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1237.                 pMovieData->idMovieInfo.width,
  1238.                 pMovieData->idMovieInfo.height );
  1239.  
  1240.         case PLAYER_MOVIE_DOUBLESIZE:
  1241.             if( ( pMovieData->wMinMaxEtc == SIZE_MAXIMIZED ) ||
  1242.                 ( pMovieData->wMinMaxEtc == SIZE_MINIMIZED ))
  1243.                 ShowWindow( hwndMovie, SW_SHOWNORMAL );
  1244.  
  1245.             return ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  1246.                 pMovieData->idMovieInfo.width * 2,
  1247.                 pMovieData->idMovieInfo.height * 2 );
  1248.  
  1249.         case PLAYER_MOVIE_SHOWPOSTER:
  1250.             trPosterTime.value.dwHi = 0L;
  1251.             trPosterTime.value.dwLo =
  1252.                 GetMoviePosterTime( pMovieData->mMovie );
  1253.             trPosterTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  1254.             trPosterTime.base  = TIMEBASE_DEFAULT;
  1255.  
  1256.             // Stop the movie
  1257.             MCDoAction( pMovieData->mcMovieController,
  1258.                 mcActionPlay, (LPVOID) 0 );
  1259.             // Go to poster time
  1260.             MCDoAction( pMovieData->mcMovieController,
  1261.                 mcActionGoToTime, (LPVOID) &trPosterTime );
  1262.             return 0L;
  1263.     }
  1264.  
  1265.     return 0L; // should never get here
  1266.  
  1267. }
  1268.  
  1269. //// the following are some utility routines
  1270.  
  1271. // Function: ActivateTheController - Activates or deactivates the movie
  1272. //                                   controller
  1273. // --------------------------------------------------------------------
  1274. // Parameters: HWND         hwndMovie       Handle of movie window
  1275. //             NPMOVIEDATA  pMovieData      -> to movie data struct
  1276. //             BOOL         bActivate       Activate flag
  1277. //
  1278. // Returns:    VOID
  1279. // --------------------------------------------------------------------
  1280. static VOID NEAR ActivateTheController
  1281.              ( HWND hwndMovie, NPMOVIEDATA pMovieData, BOOL bActivate )
  1282.  
  1283. {
  1284.     short          nVol; // Sound volume
  1285.  
  1286.     if( bActivate && ( hwndMovie != (HWND) SendMessage
  1287.         ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L )))
  1288.         return;
  1289.  
  1290.     MCActivate( pMovieData->mcMovieController, hwndMovie, bActivate );
  1291.  
  1292.     MCDoAction( pMovieData->mcMovieController,
  1293.         mcActionSetKeysEnabled, (LPVOID) bActivate );
  1294.     if( bActivate ) // RealizePalette only if activating
  1295.     {
  1296.         MCDoAction( pMovieData->mcMovieController,
  1297.             mcActionSetFlags, (LPVOID) mcFlagsUseWindowPalette );
  1298.         // InvalidateRect is needed to cause repainting in certain
  1299.         // situations when the window is iconic
  1300.         InvalidateRect( hwndMovie, NULL, TRUE );
  1301.     }
  1302.  
  1303.     MCDoAction( pMovieData->mcMovieController,
  1304.         mcActionGetVolume, (LPVOID) &nVol );
  1305.     if( ( bActivate && ( nVol < 0 )) || ( !bActivate && ( nVol > 0 )))
  1306.         MCDoAction( pMovieData->mcMovieController,
  1307.         mcActionSetVolume, (LPVOID) -nVol );
  1308. }
  1309.  
  1310.  
  1311.  
  1312. // Function: StartTheMovie - Starts the movie
  1313. // --------------------------------------------------------------------
  1314. // Parameters: NPMOVIEDATA  pMovieData      -> movie data struct
  1315. //
  1316. // Returns:    LONG         always 0L
  1317. // --------------------------------------------------------------------
  1318. static LONG NEAR StartTheMovie( NPMOVIEDATA pMovieData )
  1319.  
  1320. { // Reactivate the movie
  1321.     SetMovieActive( pMovieData->mMovie, TRUE );
  1322.   // Restart the movie if it was playing
  1323.     if( pMovieData->lfxSavePlayRate )
  1324.         MCDoAction( pMovieData->mcMovieController,
  1325.         mcActionPlay, (LPVOID) pMovieData->lfxSavePlayRate );
  1326.  
  1327.     return 0L;
  1328. }
  1329.  
  1330. // Function: StopTheMovie - Stops the movie
  1331. // --------------------------------------------------------------------
  1332. // Parameters: NPMOVIEDATA  pMovieData      -> movie data struct
  1333. //
  1334. // Returns:    LONG         always 0L
  1335. // --------------------------------------------------------------------
  1336. static LONG NEAR StopTheMovie( NPMOVIEDATA pMovieData )
  1337.  
  1338. { // save the play rate
  1339.     MCDoAction( pMovieData->mcMovieController,
  1340.         mcActionGetPlayRate, (LPVOID) &pMovieData->lfxSavePlayRate );
  1341.   // Stop the movie
  1342.     MCDoAction( pMovieData->mcMovieController,
  1343.         mcActionPlay, (LPVOID) 0 );
  1344.   // Deactivate movie to prevent painting over the icon
  1345.     SetMovieActive( pMovieData->mMovie, FALSE );
  1346.  
  1347.     return 0L;
  1348. }
  1349.  
  1350.  
  1351. // Function: PaintTheIcon - processes the WM_PAINT message when iconic
  1352. // --------------------------------------------------------------------
  1353. // Parameters: HWND         hwndPicture     Handle of Picture window
  1354. //             NPMOVIEDATA  pMovieData      -> movie data struct
  1355. //
  1356. // Returns:    LONG         0L
  1357. // --------------------------------------------------------------------
  1358. static LONG NEAR PaintTheIcon( HWND hwndMovie, NPMOVIEDATA pMovieData )
  1359.  
  1360. {
  1361.     HCURSOR          hcursorSave;   // Saved cursor
  1362.     HBRUSH           hbrush;        // Temp background brush
  1363.     PicHandle        phPoster;      // Pic handle
  1364.     PAINTSTRUCT      ps;            // Paint struct
  1365.     RECT             rcPicRect;     // Proportional pic rect
  1366.     WORD             wIconWidth;    // Icon width
  1367.     WORD             wIconHeight;   // Icon height
  1368.     WORD             wProportional; // Temp
  1369.  
  1370.     static RECT      rcIcon = {
  1371.                          2, 2, 34, 34}; // Rect used in painting icon
  1372.  
  1373.     // Make sure the entire window rect is invalidated
  1374.     InvalidateRect( hwndMovie, NULL, FALSE );
  1375.  
  1376.     if( !BeginPaint( hwndMovie, &ps ))
  1377.         return 0L;
  1378.  
  1379.     if( !pMovieData->mMovie ) {
  1380.         EndPaint( hwndMovie, &ps );
  1381.         return 0L;
  1382.     }
  1383.  
  1384.     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1385.  
  1386.     if( pMovieData->bSoundOnly ) { // Erase the entire background since there is no picture
  1387.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1388.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1389.             DeleteObject( hbrush );
  1390.         }
  1391.         // Now draw the film strip icon
  1392.         if( g.hmovieIcon )
  1393.             DrawIcon( ps.hdc, 2, 2, g.hmovieIcon );
  1394.     }
  1395.     else {
  1396.         if( phPoster = GetMoviePosterPict( pMovieData->mMovie )) {
  1397.             rcPicRect = rcIcon;
  1398.             wIconWidth  = rcIcon.right - rcIcon.left;
  1399.             wIconHeight = rcIcon.bottom - rcIcon.top;
  1400.             if( pMovieData->idMovieInfo.width >
  1401.                 pMovieData->idMovieInfo.height ) {
  1402.                 wProportional = MulDiv( wIconHeight,
  1403.                     pMovieData->idMovieInfo.width,
  1404.                     pMovieData->idMovieInfo.height );
  1405.                 rcPicRect.left  -= ( wProportional - wIconWidth ) / 2;
  1406.                 rcPicRect.right = rcPicRect.left + wProportional;
  1407.             }
  1408.             else if( pMovieData->idMovieInfo.width <
  1409.                 pMovieData->idMovieInfo.height ) {
  1410.                 wProportional = MulDiv( wIconWidth,
  1411.                     pMovieData->idMovieInfo.height,
  1412.                     pMovieData->idMovieInfo.width );
  1413.                 rcPicRect.top  -= ( wProportional - wIconHeight ) / 2;
  1414.                 rcPicRect.bottom = rcPicRect.top + wProportional;
  1415.             }
  1416.  
  1417.             // Draw the poster frame
  1418.             if( DrawPicture( ps.hdc, phPoster, &rcPicRect, NULL )) {
  1419.                 CommonTellUser( PlayerQueryResources(),
  1420.                     PLAYER_STRING_DRAWPICFAILED,
  1421.                     PLAYER_STRING_CAPTION, MB_OK );
  1422.  
  1423.                 // Validate rect to prevent infinite loop
  1424.                 ValidateRect( hwndMovie, NULL );
  1425.                 DisposePicture( phPoster );
  1426.                 SetCursor( hcursorSave );
  1427.                 EndPaint( hwndMovie, &ps );
  1428.                 return 0L;
  1429.             }
  1430.             else {
  1431.                 DisposePicture( phPoster );
  1432.             }
  1433.         }
  1434.  
  1435.         // Now draw the film strip icon
  1436.         if( g.hmovieIcon )
  1437.             DrawIcon( ps.hdc, 2, 2, g.hmovieIcon );
  1438.  
  1439.         // Now paint background
  1440.         ExcludeClipRect( ps.hdc, rcIcon.left, rcIcon.top,
  1441.             rcIcon.right, rcIcon.bottom );
  1442.         // COLOR_APPWORKSPACE is standard MDI background color
  1443.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1444.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1445.             DeleteObject( hbrush );
  1446.         }
  1447.     }
  1448.  
  1449.     SetCursor( hcursorSave );
  1450.     EndPaint( hwndMovie, &ps );
  1451.  
  1452.     return 0L;
  1453.  
  1454. }
  1455.  
  1456.  
  1457. // Function: PrintFrame - prints indicated number of copies of
  1458. //                        the selected frame at normal size
  1459. // --------------------------------------------------------------------
  1460. // Parameters: HWND         hwndMovie       Handle of movie window
  1461. //             LPPRINTDLG   lppd            -> to PRINTDLG struct created
  1462. //                                          print common dialog
  1463. //
  1464. // Returns:    LONG         0L if successful
  1465. // --------------------------------------------------------------------
  1466. static LONG NEAR PrintFrame( HWND hwndMovie, LPPRINTDLG lppd )
  1467.  
  1468. {
  1469.     NPMOVIEDATA     pMovieData;  // -> movie data struct
  1470.     WORD            i;           // Counter
  1471.     DOCINFO         diDocInfo;   // Document info struct
  1472.     PicHandle       phFrame;     // Pichandle of current frame
  1473.     BOOL            bError;      // Error flag
  1474.     int             nError;      // Error return
  1475.     OSErr           oserr;       // Error return from DrawPicture
  1476.     int             xRes;        // Horz printer resolution
  1477.     int             yRes;        // Vert printer resolution
  1478.     int             xOffset;     // Horz offset to center picture
  1479.     int             yOffset;     // Vert offset to center picture
  1480.     RECT            rcFrame;     // Frame rect
  1481.     WORD            wWidthPage;  // Width of printed page in pixels
  1482.     WORD            wHeightPage; // Height of printed page in pixels
  1483.     TimeRecord      trMovieTime; // Temp time record
  1484.  
  1485.  
  1486.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1487.         CommonTellUser( PlayerQueryResources(),
  1488.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  1489.         // Turn off not reported flag
  1490.         return SP_ERROR &  ~SP_NOTREPORTED;
  1491.     }
  1492.  
  1493.     diDocInfo.cbSize      = sizeof( DOCINFO );
  1494.     diDocInfo.lpszDocName = pMovieData->szMovieName;
  1495.     diDocInfo.lpszOutput  = (LPSTR) NULL;
  1496.  
  1497.     if( !(phFrame = GetMoviePict( pMovieData->mMovie,
  1498.         GetMovieTime( pMovieData->mMovie, &trMovieTime )))) {
  1499.         CommonTellUser( PlayerQueryResources(),
  1500.             PLAYER_STRING_GETPICTFAILED, PLAYER_STRING_CAPTION, MB_OK );
  1501.         // Turn off not reported flag
  1502.         return SP_ERROR &  ~SP_NOTREPORTED;
  1503.     }
  1504.  
  1505.     wWidthPage  = GetDeviceCaps( lppd->hDC, HORZRES );
  1506.     wHeightPage = GetDeviceCaps( lppd->hDC, VERTRES );
  1507.  
  1508.     xRes = MulDiv( wWidthPage, 254,
  1509.         GetDeviceCaps( lppd->hDC, HORZSIZE ) * 10 );
  1510.     yRes = MulDiv( wHeightPage, 254,
  1511.         GetDeviceCaps( lppd->hDC, VERTSIZE ) * 10 );
  1512.     rcFrame.right  = MulDiv( pMovieData->idMovieInfo.width,
  1513.         xRes, HIWORD( pMovieData->idMovieInfo.hRes ));
  1514.     rcFrame.bottom = MulDiv( pMovieData->idMovieInfo.height,
  1515.         yRes, HIWORD( pMovieData->idMovieInfo.vRes ));
  1516.     rcFrame.left = rcFrame.top = 0;
  1517.  
  1518.     // Now make sure that frame fits on page
  1519.     if( rcFrame.right > (int) wWidthPage ) {
  1520.         rcFrame.bottom = MulDiv( rcFrame.bottom,
  1521.             wWidthPage, rcFrame.right );
  1522.         rcFrame.right = wWidthPage;
  1523.     }
  1524.     if( rcFrame.bottom > (int) wHeightPage ) {
  1525.         rcFrame.right = MulDiv( rcFrame.right,
  1526.             wHeightPage, rcFrame.bottom );
  1527.         rcFrame.bottom = wHeightPage;
  1528.     }
  1529.  
  1530.     // Now center rect on page
  1531.     xOffset = (wWidthPage  - rcFrame.right ) / 2;
  1532.     yOffset = (wHeightPage - rcFrame.bottom ) / 2;
  1533.     OffsetRect( &rcFrame, xOffset, yOffset );
  1534.  
  1535.     bError = FALSE;
  1536.     oserr  = 0L;
  1537.     nError = SP_ERROR;
  1538.  
  1539.     if( StartDoc( lppd->hDC, &diDocInfo ) > 0 ) {
  1540.         for( i=0; (i < lppd->nCopies) && !bError; i++ ) {
  1541.             if( StartPage( lppd->hDC ) > 0) {
  1542.                 if( (oserr = DrawPicture
  1543.                     ( lppd->hDC, phFrame, &rcFrame, NULL )) != 0L ) {
  1544.                     AbortDoc( lppd->hDC );
  1545.                     bError = TRUE;
  1546.                 }
  1547.                 else if( (nError = EndPage( lppd->hDC )) < 0 )
  1548.                     bError = TRUE;
  1549.             }
  1550.             else
  1551.                 bError = TRUE;
  1552.         }
  1553.     }
  1554.     else
  1555.         bError = TRUE;
  1556.  
  1557.     if( !bError )
  1558.         EndDoc( lppd->hDC );
  1559.  
  1560.     if( phFrame )
  1561.         DisposePicture( phFrame );
  1562.  
  1563.     return (LONG) nError;
  1564. }
  1565.  
  1566.  
  1567. // Function: SetMinMaxInfo - Processes the WM_GETMINMAXINFO message
  1568. // --------------------------------------------------------------------
  1569. // Parameters: HWND               hwndMovie     Handle of movie wnd
  1570. //             NPMOVIEDATA        pMovieData    -> to movie data
  1571. //             MINMAXINFO FAR*    lpmmi         -> to minmaxinfo struct
  1572. //
  1573. // Returns:    LONG               always 0L
  1574. // --------------------------------------------------------------------
  1575. static LONG NEAR SetMinMaxInfo
  1576.       ( HWND hwndMovie, NPMOVIEDATA pMovieData, MINMAXINFO FAR* lpmmi )
  1577.  
  1578. {
  1579.     RECT   rcWindow; // Movie window rect
  1580.  
  1581.     if( PlayerQueryMDIAction() == PLAYER_WINDOW_CASCADE ) {
  1582.         GetWindowRect( hwndMovie, &rcWindow );
  1583.         lpmmi->ptMaxTrackSize.x = rcWindow.right - rcWindow.left;
  1584.         lpmmi->ptMaxTrackSize.y = rcWindow.bottom - rcWindow.top;
  1585.         lpmmi->ptMinTrackSize = lpmmi->ptMaxTrackSize;
  1586.         lpmmi->ptMaxSize      = lpmmi->ptMaxTrackSize;
  1587.     }
  1588.     else {
  1589.         lpmmi->ptMinTrackSize.x = 3 * GetSystemMetrics( SM_CXSIZE );
  1590.         lpmmi->ptMinTrackSize.y = GetSystemMetrics( SM_CYCAPTION ) +
  1591.             g.wMovieControllerHeight +
  1592.             2 * GetSystemMetrics( SM_CYFRAME );
  1593.         // Disable vertical resizing if sound only movie
  1594.         if( pMovieData && pMovieData->bSoundOnly ) {
  1595.             lpmmi->ptMinTrackSize.y -= 2;
  1596.             lpmmi->ptMaxTrackSize.y = lpmmi->ptMinTrackSize.y;
  1597.         }
  1598.     }
  1599.  
  1600.     return 0L;
  1601. }
  1602.  
  1603.  
  1604. // Function: GetInfoDlgProc - Get Info dialog proc
  1605. // --------------------------------------------------------------------
  1606. // Parameters: As required by Microsoft Windows
  1607. //
  1608. // Returns:    As required by Microsoft Windows
  1609. // --------------------------------------------------------------------
  1610. BOOL __export CALLBACK GetInfoDlgProc
  1611.     ( HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam )
  1612.  
  1613. {
  1614.     NPMOVIEDATA   pMovieData; // -> movie data struct
  1615.     HWND          hwndMovie;  // HWND of movie window
  1616.     HWND          hwndCtl;    // Handle of control
  1617.     HDC           hdc;        // DC of dialog
  1618.     int           nHeight;    // Height of control text font
  1619.  
  1620.     switch( message ) {
  1621.         case WM_INITDIALOG:
  1622.             hwndMovie = (HWND) SendMessage
  1623.                 ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  1624.  
  1625.             // Use property to associate movie window handle with
  1626.             // info dialog. This is necessary because MDI makes frame
  1627.             // window the parent of all dialogs no matter what handle
  1628.             // is used in the CreateDialog call
  1629.             SetProp( hdlg, GETINFOMOVIEPROP, (HANDLE) hwndMovie );
  1630.  
  1631.             if( pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )) {
  1632.                 pMovieData->hwndGetInfo = hdlg;
  1633.                 // Cache selection strings to speed up updates
  1634.                 if( !g.szSelectFormat[0] )
  1635.                     LoadString( PlayerQueryResources(),
  1636.                     PLAYER_STRING_SELECTION,
  1637.                     g.szSelectFormat, sizeof( g.szSelectFormat ));
  1638.                 if( !g.szNoSelection[0] )
  1639.                     LoadString( PlayerQueryResources(),
  1640.                     PLAYER_STRING_NOSELECTION,
  1641.                     g.szNoSelection, sizeof( g.szNoSelection ));
  1642.  
  1643.                 if( hdc = GetDC( hdlg )) {
  1644.                     nHeight = -MulDiv( 8, GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
  1645.                     if( pMovieData->hfInfo = MakeAnArialFont( hdc, nHeight )) {
  1646.                         hwndCtl = GetWindow( hdlg, GW_CHILD );
  1647.                         while( hwndCtl ) {
  1648.                             if( GetDlgCtrlID( hwndCtl ) != IDOK )
  1649.                                 SendMessage( hwndCtl, WM_SETFONT,
  1650.                                 (WPARAM) pMovieData->hfInfo, 0 );
  1651.                             hwndCtl = GetWindow( hwndCtl, GW_HWNDNEXT );
  1652.                         }
  1653.                     }
  1654.                     ReleaseDC( hdlg, hdc );
  1655.                 }
  1656.  
  1657.                 FillMovieInfo( hdlg, pMovieData );
  1658.             }
  1659.  
  1660.             return TRUE;
  1661.  
  1662.         case WM_ACTIVATE:
  1663.             PlayerSetActiveModeless( wParam, hdlg );
  1664.             return TRUE;
  1665.  
  1666.         // WM_USER messages
  1667.  
  1668.         case WM_PLAYER_INFO_UPDATEFILENAME:
  1669.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1670.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1671.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )))
  1672.                 UpdateInfoFileName( pMovieData );
  1673.             break;
  1674.  
  1675.         case WM_PLAYER_INFO_UPDATE:
  1676.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1677.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1678.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 )))
  1679.                 FillMovieInfo( hdlg, pMovieData );
  1680.             break;
  1681.  
  1682.         // End WM_USER messages
  1683.  
  1684.         case WM_COMMAND:
  1685.             return DestroyWindow( hdlg );
  1686.  
  1687.         case WM_DESTROY:
  1688.             hwndMovie = (HWND) GetProp( hdlg, GETINFOMOVIEPROP );
  1689.             if( IsWindow( hwndMovie ) && ( pMovieData =
  1690.                 (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  1691.                 pMovieData->hwndGetInfo = NULL;
  1692.  
  1693.                 if( pMovieData->hfInfo )
  1694.                     DeleteObject( pMovieData->hfInfo );
  1695.                 pMovieData->hfInfo = NULL;
  1696.             }
  1697.  
  1698.             RemoveProp( hdlg, GETINFOMOVIEPROP );
  1699.             break;
  1700.     }
  1701.  
  1702.     return FALSE;
  1703.  
  1704. }
  1705.  
  1706.  
  1707. // Function: FillMovieInfo - Fills dialog controls with movie data
  1708. // --------------------------------------------------------------------
  1709. // Parameters: HWND          hdlg            Handle of dialog wnd
  1710. //             NPMOVIEDATA   pMovieData      -> movie data struct
  1711. //
  1712. // Returns:    VOID
  1713. // --------------------------------------------------------------------
  1714. static VOID NEAR FillMovieInfo( HWND hdlg, NPMOVIEDATA pMovieData )
  1715.  
  1716. {
  1717.     char           szBuffer[MAX_PATH_LEN];          // Buffer
  1718.     char           szFormat[30];                    // Format buffer
  1719.     TimeValue      tvDuration;                      // Duration of movie
  1720.     double         fTimeScale;                      // Timescale
  1721.     RECT           rcMovie;                         // Current movie rect
  1722.     DWORD          dwColors;                        // Number of colors
  1723.     char           szCompressor[sizeof(DWORD) + 1]; // compressor type
  1724.     WORD           wIDString;                       // Colors string id
  1725.     DWORD          dwRate;                          // Sound sample rate
  1726.     DWORD          dwKRate;                         // Sound sample rate
  1727.     char           szNull[] = "";                   // Static null string
  1728.  
  1729.     g.bUpdatingInfo = TRUE;
  1730.  
  1731.     // Movie name: Append duplication index if > 0
  1732.     UpdateInfoFileName( pMovieData );
  1733.  
  1734.     // file size
  1735.     SetDlgItemText( hdlg, MOVIE_INFO_FILESIZE, pMovieData->szFileSize );
  1736.  
  1737.     // Get movie time scale
  1738.     if( ( fTimeScale = (double)
  1739.         GetMovieTimeScale( pMovieData->mMovie )) != 0. ) { // Do these only if timescale != zero to avoid divide by 0
  1740.                                                            // Movie duration
  1741.         tvDuration = GetMovieDuration( pMovieData->mMovie );
  1742.         LoadString( PlayerQueryResources(), PLAYER_STRING_DURATION,
  1743.             szFormat, sizeof( szFormat ));
  1744.         sprintf( szBuffer, szFormat, tvDuration / fTimeScale );
  1745.         SetDlgItemText( hdlg, MOVIE_INFO_DURATION, szBuffer );
  1746.  
  1747.         // Current selection
  1748.         DisplayCurrentSelection( pMovieData );
  1749.     }
  1750.  
  1751.     if( !pMovieData->bSoundOnly ) { // Current size
  1752.         LoadString( PlayerQueryResources(), PLAYER_STRING_WANDH,
  1753.             szFormat, sizeof( szFormat ));
  1754.         GetMovieBox( pMovieData->mMovie, &rcMovie );
  1755.  
  1756.         wsprintf( szBuffer, szFormat, rcMovie.right - rcMovie.left,
  1757.             rcMovie.bottom - rcMovie.top );
  1758.         SetDlgItemText( hdlg, MOVIE_INFO_CURSIZE, szBuffer );
  1759.  
  1760.         // Normal Width and Height
  1761.         wsprintf( szBuffer, szFormat,
  1762.             pMovieData->idMovieInfo.width,
  1763.             pMovieData->idMovieInfo.height );
  1764.         SetDlgItemText( hdlg, MOVIE_INFO_WANDH, szBuffer );
  1765.         wsprintf( szBuffer, szFormat, pMovieData->idMovieInfo.height );
  1766.  
  1767.         // Resolution
  1768.         if( HIWORD( pMovieData->idMovieInfo.hRes ) != 0 ) {
  1769.             LoadString( PlayerQueryResources(),
  1770.                 PLAYER_STRING_RESOLUTION, szFormat, sizeof( szFormat ));
  1771.             wsprintf( szBuffer, szFormat,
  1772.                 HIWORD( pMovieData->idMovieInfo.hRes ));
  1773.         }
  1774.         else {
  1775.             LoadString( PlayerQueryResources(),
  1776.                 PLAYER_STRING_NORESOLUTION, szBuffer, sizeof( szBuffer ));
  1777.         }
  1778.         SetDlgItemText( hdlg, MOVIE_INFO_RESOLUTION, szBuffer );
  1779.  
  1780.  
  1781.         // Normal colors
  1782.         switch( pMovieData->idMovieInfo.depth ) {
  1783.             case 1:      // Black and White
  1784.                 wIDString = PLAYER_STRING_CLRS_BANDW;      
  1785.                 break;
  1786.             case 1 + 32: // 2 Grays
  1787.                 wIDString = PLAYER_STRING_CLRS_2GRAYS;     
  1788.                 break;
  1789.             case 2:      // 4 Colors
  1790.                 wIDString = PLAYER_STRING_CLRS_4COLORS;    
  1791.                 break;
  1792.             case 2 + 32: // 4 Grays
  1793.                 wIDString = PLAYER_STRING_CLRS_4GRAYS;     
  1794.                 break;
  1795.             case 4:      // 16 Colors
  1796.                 wIDString = PLAYER_STRING_CLRS_16COLORS;   
  1797.                 break;
  1798.             case 4 + 32: // 16 Grays
  1799.                 wIDString = PLAYER_STRING_CLRS_16GRAYS;    
  1800.                 break;
  1801.             case 8:      // 256 Colors
  1802.                 wIDString = PLAYER_STRING_CLRS_256COLORS;  
  1803.                 break;
  1804.             case 8 + 32: // 256 Grays
  1805.                 wIDString = PLAYER_STRING_CLRS_256GRAYS;   
  1806.                 break;
  1807.             case 16:     // Thousands of Colors
  1808.                 wIDString = PLAYER_STRING_CLRS_THOUSANDS;  
  1809.                 break;
  1810.             case 24:     // Millions of Colors
  1811.                 wIDString = PLAYER_STRING_CLRS_MILLIONS;   
  1812.                 break;
  1813.             case 32:     // Millions of Colors+
  1814.                 wIDString = PLAYER_STRING_CLRS_MILLNSPLUS; 
  1815.                 break;
  1816.             default:
  1817.                 wIDString = 0xffff;
  1818.                 if( pMovieData->idMovieInfo.depth < 32 ) {
  1819.                     LoadString( PlayerQueryResources(), PLAYER_STRING_COLORS,
  1820.                         szFormat, sizeof( szFormat ));
  1821.                     dwColors = 1L << pMovieData->idMovieInfo.depth;
  1822.                     wsprintf( szBuffer, szFormat, dwColors );
  1823.                 }
  1824.                 else {
  1825.                     szBuffer[0] = '\0';
  1826.                 }
  1827.                 break;
  1828.         }
  1829.         if( wIDString != 0xffff )
  1830.             LoadString( PlayerQueryResources(), wIDString,
  1831.             szBuffer, sizeof( szBuffer ));
  1832.         SetDlgItemText( hdlg, MOVIE_INFO_COLORS, szBuffer );
  1833.  
  1834.         // Compressor type. Use .name if not empty
  1835.         if( pMovieData->idMovieInfo.name[0] ) {
  1836.             SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR,
  1837.                 pMovieData->idMovieInfo.name );
  1838.         }
  1839.         else // Check Codec type for 'raw'
  1840.         { // Compressor type is stored as a DWORD. i.e. 'jpeg'
  1841.           // Spaces in "raw ", "rle " etc are necessary !!!
  1842.             if( pMovieData->idMovieInfo.CodecType ) {
  1843.                 *((PDWORD) &szCompressor) = pMovieData->idMovieInfo.CodecType;
  1844.                 szCompressor[ sizeof(DWORD) ] = '\0';
  1845.             }
  1846.             szBuffer[0] = '\0';
  1847.             if( !pMovieData->idMovieInfo.CodecType ||
  1848.                 !lstrcmpi( szCompressor, "raw " ))
  1849.                 wIDString = PLAYER_STRING_CODEC_NONE;
  1850.             else if( !lstrcmpi( szCompressor, "jpeg" ))
  1851.                 wIDString = PLAYER_STRING_CODEC_PHOTO;
  1852.             else if( !lstrcmpi( szCompressor, "rle " ))
  1853.                 wIDString = PLAYER_STRING_CODEC_ANIMATION;
  1854.             else if( !lstrcmpi( szCompressor, "smc " ))
  1855.                 wIDString = PLAYER_STRING_CODEC_GRAPHICS;
  1856.             else if( !lstrcmpi( szCompressor, "rpza" ))
  1857.                 wIDString = PLAYER_STRING_CODEC_VIDEO;
  1858.             else if( !lstrcmpi( szCompressor, "cvid" ))
  1859.                 wIDString = PLAYER_STRING_CODEC_CVID;
  1860.             else
  1861.                 wIDString = PLAYER_STRING_CODEC_NONE;
  1862.  
  1863.             LoadString( PlayerQueryResources(), wIDString,
  1864.                 szBuffer, sizeof( szBuffer ));
  1865.  
  1866.             SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR, szBuffer );
  1867.         }
  1868.     }
  1869.     else {
  1870.         LoadString( PlayerQueryResources(),
  1871.             PLAYER_STRING_NOVIDEO, szBuffer, sizeof( szBuffer ));
  1872.         SetDlgItemText( hdlg, MOVIE_INFO_CURSIZE,    szBuffer );
  1873.         SetDlgItemText( hdlg, MOVIE_INFO_WANDH,      szNull );
  1874.         SetDlgItemText( hdlg, MOVIE_INFO_RESOLUTION, szNull );
  1875.         SetDlgItemText( hdlg, MOVIE_INFO_COLORS,     szNull );
  1876.         SetDlgItemText( hdlg, MOVIE_INFO_COMPRESSOR, szNull );
  1877.     }
  1878.  
  1879.     // Sound info
  1880.     if( pMovieData->oserrSoundInfo == noSoundTrackInMovie ) {
  1881.         LoadString( PlayerQueryResources(),
  1882.             PLAYER_STRING_SND_NOSOUND, szBuffer, sizeof( szBuffer ));
  1883.         SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1884.         SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1885.     }
  1886.     else if( pMovieData->oserrSoundInfo == soundSupportNotAvailable ) {
  1887.         LoadString( PlayerQueryResources(),
  1888.             PLAYER_STRING_SND_NOCARD, szBuffer, sizeof( szBuffer ));
  1889.         SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1890.         SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szNull );
  1891.     }
  1892.     else if( pMovieData->oserrSoundInfo ) { // GetSoundInfo call failed so doen't write anything
  1893.     }
  1894.     else { // Num of channels
  1895.         if( pMovieData->sdSoundInfo.numChannels == 1 )
  1896.             LoadString( PlayerQueryResources(), PLAYER_STRING_SND_MONO,
  1897.             szBuffer, sizeof( szBuffer ));
  1898.         else
  1899.             LoadString( PlayerQueryResources(), PLAYER_STRING_SND_STEREO,
  1900.             szBuffer, sizeof( szBuffer ));
  1901.         SetDlgItemText( hdlg, MOVIE_INFO_SND_NUMCHANNELS, szBuffer );
  1902.  
  1903.         // Sample size and rate
  1904.         LoadString( PlayerQueryResources(),
  1905.             PLAYER_STRING_SND_SOUNDQUALITY, szFormat, sizeof( szFormat ));
  1906.         dwRate = ((DWORD) pMovieData->sdSoundInfo.sampleRate ) / 65536L;
  1907.         dwKRate = dwRate / 1000;
  1908.         dwRate -= dwKRate * 1000;
  1909.         wsprintf( szBuffer, szFormat,
  1910.             pMovieData->sdSoundInfo.sampleSize, dwKRate, dwRate );
  1911.         SetDlgItemText( hdlg, MOVIE_INFO_SND_SOUNDQUALITY, szBuffer );
  1912.     }
  1913.  
  1914.     // End sound info
  1915.  
  1916.     g.bUpdatingInfo = FALSE;
  1917.  
  1918.     return;
  1919. }
  1920.  
  1921.  
  1922. // Function: UpdateInfoFileName - Updates the file name with the current
  1923. //                                instance count in the info dialog
  1924. // --------------------- -----------------------------------------------
  1925. // Parameters: NPMOVIEDATA    pMovieData       -> to MOVIEDATA struct
  1926. //
  1927. // Returns:    VOID
  1928. // --------------------------------------------------------------------
  1929. static VOID NEAR UpdateInfoFileName( NPMOVIEDATA pMovieData )
  1930.  
  1931. {
  1932.     char      szBuffer[MAX_NAME_LEN + 10]; // Buffer
  1933.     char      szFormat[20];                // Format buffer
  1934.  
  1935.     lstrcpy( szFormat, "%s%s" );
  1936.     if( pMovieData->wDuplicationIndex > 0 )
  1937.         lstrcat( szFormat, ":%u" );
  1938.     wsprintf( szBuffer, szFormat, (LPSTR) pMovieData->szMovieName,
  1939.         (LPSTR) pMovieData->szMovieExt,
  1940.         pMovieData->wDuplicationIndex );
  1941.     AnsiUpper( szBuffer );
  1942.     SetDlgItemText( pMovieData-> hwndGetInfo,
  1943.         MOVIE_INFO_NAME, (LPSTR) szBuffer );
  1944.  
  1945.     return;
  1946. }
  1947.  
  1948.  
  1949. // Function:  DisplayCurrentSelection - Displays the current selection in
  1950. //                                      the info dialog
  1951. // --------------------------------------------------------------------
  1952. // Parameters: NPMOVIEDATA      pMovieData        -> movie data struct
  1953. //
  1954. // Returns:    VOID
  1955. // --------------------------------------------------------------------
  1956. static VOID NEAR DisplayCurrentSelection( NPMOVIEDATA pMovieData )
  1957.  
  1958. {
  1959.     char     szBuffer[100];   // Buffer
  1960.     double   fSelectionStart; // Beginning of selection
  1961.     double   fSelectionEnd;   // End of selection
  1962.     double   fTimeScale;      // Time scale of movie
  1963.  
  1964.     if( ( ( fTimeScale = (double)
  1965.         GetMovieTimeScale( pMovieData->mMovie )) != 0. ) &&
  1966.         ( pMovieData->trSelectionStart.value.dwLo != (DWORD) -1) &&
  1967.         ( pMovieData->trSelectionDuration.value.dwLo > 0L )) {
  1968.         fSelectionStart = pMovieData->trSelectionStart.value.dwLo /
  1969.             fTimeScale ;
  1970.         fSelectionEnd = fSelectionStart +
  1971.             pMovieData->trSelectionDuration.value.dwLo /
  1972.             fTimeScale ;
  1973.  
  1974.         sprintf( szBuffer, g.szSelectFormat, fSelectionStart, fSelectionEnd );
  1975.         SetDlgItemText( pMovieData-> hwndGetInfo,
  1976.             MOVIE_INFO_SELECTION, szBuffer );
  1977.     }
  1978.     else {
  1979.         SetDlgItemText( pMovieData-> hwndGetInfo,
  1980.             MOVIE_INFO_SELECTION, g.szNoSelection );
  1981.     }
  1982.  
  1983.     return;
  1984.  
  1985. }
  1986.  
  1987.  
  1988. // Function: ActionFilter - Used to filter the selection change message
  1989. // --------------------------------------------------------------------
  1990. // Parameters: MovieController  mcController      Movie controller
  1991. //             UNIT             psAction          action parameter
  1992. //             LPVOID           lpParm            DoAction parameter
  1993. //             LONG             lUserData         User defined data
  1994. //
  1995. // Returns:    BOOL             TRUE  if no further action
  1996. //                              FALSE if controller is to perform action
  1997. // --------------------------------------------------------------------
  1998. BOOL __export CALLBACK ActionFilter
  1999.     ( MovieController mcController, UINT psAction,
  2000.     LPVOID lpParm, LONG lUserData )
  2001.  
  2002. {
  2003.     NPMOVIEDATA         pMovieData; // -> movie data struct
  2004.  
  2005.     switch( psAction ) {
  2006.         case mcActionControllerSizeChanged:
  2007.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2008.             if( !pMovieData->bSettingControllerSize ) {
  2009.                 ResizeMovieAndWindow( (HWND) HIWORD( lUserData ),
  2010.                     FALSE, pMovieData, 0, 0 );
  2011.                 if( pMovieData->hwndGetInfo && !g.bUpdatingInfo ) { // Need to post message here because FALSE second
  2012.                                                                     // parameter prevents ResizeMovie from being called
  2013.                                                                     // by ResizeMovieAndWindow.
  2014.                                                                     // WM_PLAYER_INFO_UPDATE is defined to be in
  2015.                                                                     // the range WM_COALESCE_FIRST to WM_COALESCE_LAST
  2016.                                                                     // which tells Windows to prevent duplicate messages
  2017.                                                                     // from appearing in the queue.
  2018.                     PostMessage( pMovieData->hwndGetInfo,
  2019.                         WM_PLAYER_INFO_UPDATE, 0, 0L );
  2020.                 }
  2021.             }
  2022.             else {
  2023.                 pMovieData->bSettingControllerSize = FALSE;
  2024.             }
  2025.  
  2026.             break;
  2027.  
  2028.         case mcActionSetSelectionBegin:
  2029.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2030.             pMovieData->trSelectionStart = *( TimeRecord FAR *) lpParm;
  2031.  
  2032.             break;
  2033.  
  2034.         case mcActionSetSelectionDuration:
  2035.             pMovieData = (NPMOVIEDATA) LOWORD( lUserData );
  2036.             pMovieData->trSelectionDuration = *( TimeRecord FAR *) lpParm;
  2037.  
  2038.             if( pMovieData->hwndGetInfo )
  2039.                 DisplayCurrentSelection( pMovieData );
  2040.             break;
  2041.  
  2042.         default:
  2043.             break;
  2044.     }
  2045.  
  2046.     return FALSE;
  2047. }
  2048.  
  2049.  
  2050. // Function: InitializePopupMenus - Called just before the popup menus
  2051. //                                  are displayed
  2052. // --------------------------------------------------------------------
  2053. // Parameters: HWND         hwndMovie       Handle of movie window
  2054. //             HMENU        hmenuPopup      Handle of popup menu
  2055. //             int          nPopupIndex     Index of popup
  2056. //
  2057. // Returns:    LONG         0L if successful
  2058. // --------------------------------------------------------------------
  2059. static LONG NEAR InitializePopupMenus
  2060.                 ( HWND hwndMovie, HMENU hmenuPopup, int nPopupIndex )
  2061.  
  2062. {
  2063.     NPMOVIEDATA   pMovieData;         // -> movie data struct
  2064.     LONG          lControllerInfo;    // Controller info
  2065.     BOOL          bLooping;           // TRUE if looping
  2066.     BOOL          bPalindrome;        // TRUE if looping palindrome
  2067.     BOOL          bPlaySelectionOnly; // TRUE if playing selection only
  2068.     WORD          wSelectedSize;      // Nonzero if movie is a standard size
  2069.     RECT          rcMovie;            // Movie rect
  2070.     WORD          wMovieWidth;        // Width of movie
  2071.     WORD          wMovieHeight;       // Height of movie
  2072.     char          szTitle[64];        // OLE Client doc title
  2073.     char          szItemFormat1[32];  // Item format string
  2074.     char          szItem1[128];       // New item string
  2075.     char          szItemFormat2[32];  // Item format string
  2076.     char          szItem2[128];       // New item string
  2077.  
  2078.  
  2079.  
  2080.     if( !(pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))) {
  2081.         CommonTellUser( PlayerQueryResources(),
  2082.             PLAYER_STRING_NOMOVIEDATA, PLAYER_STRING_CAPTION, MB_OK );
  2083.         return 0L;
  2084.     }
  2085.  
  2086.     MCGetControllerInfo( pMovieData->mcMovieController,
  2087.         &lControllerInfo );
  2088.  
  2089.     // Decrement index if maximized since MDI adds a system menu item
  2090.     // which puts count off by one
  2091.     if( IsZoomed( hwndMovie ))
  2092.         nPopupIndex--;
  2093.  
  2094.     if( nPopupIndex == MENU_FILE_POS ) { // See if wnd is an activated client object
  2095.         if( QTOLE_IsActiveObjectWnd
  2096.             ( PlayerQueryOleData(), hwndMovie, szTitle )) {
  2097.             LoadString( PlayerQueryResources(),
  2098.                 PLAYER_STRING_OLECLOSE, szItemFormat1, sizeof( szItemFormat1 ));
  2099.             wsprintf( szItem1, szItemFormat1, (LPSTR) szTitle );
  2100.  
  2101.             LoadString( PlayerQueryResources(),
  2102.                 PLAYER_STRING_OLEEXIT, szItemFormat2, sizeof( szItemFormat2 ));
  2103.             wsprintf( szItem2, szItemFormat2, (LPSTR) szTitle );
  2104.         }
  2105.         else {
  2106.             LoadString( PlayerQueryResources(),
  2107.                 PLAYER_STRING_CLOSE, szItem1, sizeof( szItem1 ));
  2108.             LoadString( PlayerQueryResources(),
  2109.                 PLAYER_STRING_EXIT, szItem2, sizeof( szItem2 ));
  2110.         }
  2111.  
  2112.         DeleteMenu( hmenuPopup, PLAYER_FILE_CLOSE, MF_BYCOMMAND );
  2113.         InsertMenu( hmenuPopup, 1, MF_BYPOSITION,
  2114.             PLAYER_FILE_CLOSE, szItem1 );
  2115.         DeleteMenu( hmenuPopup, PLAYER_FILE_EXIT, MF_BYCOMMAND );
  2116.         InsertMenu( hmenuPopup, (UINT) -1, MF_BYPOSITION,
  2117.             PLAYER_FILE_EXIT, szItem2 );
  2118.  
  2119.         EnableMenuItem( hmenuPopup, PLAYER_FILE_PRINT,
  2120.             ( pMovieData->bSoundOnly ||
  2121.             (lControllerInfo & mcInfoIsPlaying)) ? MF_GRAYED: MF_ENABLED );
  2122.         EnableMenuItem( hmenuPopup, PLAYER_FILE_PRTSETUP,
  2123.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2124.     }
  2125.     else if( nPopupIndex == MENU_EDIT_POS ) {
  2126.         EnableMenuItem( hmenuPopup, PLAYER_EDIT_COPY,
  2127.             ( IsIconic( hwndMovie ) ||
  2128.             ( lControllerInfo & mcInfoIsPlaying )) ? MF_GRAYED: MF_ENABLED );
  2129.         EnableMenuItem( hmenuPopup, PLAYER_EDIT_OPTIONS,
  2130.             ( IsIconic( hwndMovie ) ||
  2131.             ( lControllerInfo & mcInfoIsPlaying )) ? MF_GRAYED: MF_ENABLED );
  2132.  
  2133.     }
  2134.     else if( nPopupIndex == MENU_MOVIE_POS ) {
  2135.         bLooping    = (( lControllerInfo & mcInfoIsLooping ) != 0L );
  2136.         bPalindrome = (( lControllerInfo & mcInfoIsInPalindrome ) != 0L );
  2137.  
  2138.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_STOPATEND,
  2139.             ( bLooping || bPalindrome ) ? MF_UNCHECKED: MF_CHECKED );
  2140.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_LOOP,
  2141.             ( bLooping && !bPalindrome ) ? MF_CHECKED: MF_UNCHECKED );
  2142.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_BACKANDFORTH,
  2143.             ( bLooping && bPalindrome ) ? MF_CHECKED: MF_UNCHECKED );
  2144.  
  2145.         // Toggle play selection only
  2146.         MCDoAction( pMovieData->mcMovieController,
  2147.             mcActionGetPlaySelection, (LPVOID) &bPlaySelectionOnly );
  2148.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_PLAYSELONLY,
  2149.             ( bPlaySelectionOnly ) ? MF_CHECKED: MF_UNCHECKED );
  2150.  
  2151.  
  2152.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_HALFSIZE,
  2153.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2154.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_NORMALSIZE,
  2155.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2156.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_DOUBLESIZE,
  2157.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2158.  
  2159.         // Set selected size parameter if movie is a standard size
  2160.         if( IsIconic( hwndMovie ))
  2161.             wSelectedSize = 0;
  2162.         else {
  2163.             GetMovieBox( pMovieData->mMovie, &rcMovie );
  2164.             wMovieWidth  = rcMovie.right - rcMovie.left;
  2165.             wMovieHeight = rcMovie.bottom - rcMovie.top;
  2166.  
  2167.             if( ( wMovieWidth == pMovieData->idMovieInfo.width ) &&
  2168.                 ( wMovieHeight == pMovieData->idMovieInfo.height ))
  2169.                 wSelectedSize = PLAYER_MOVIE_NORMALSIZE;
  2170.             else if( ( wMovieWidth == pMovieData->idMovieInfo.width * 2 ) &&
  2171.                 ( wMovieHeight == pMovieData->idMovieInfo.height * 2 ))
  2172.                 wSelectedSize = PLAYER_MOVIE_DOUBLESIZE;
  2173.             else if( ( wMovieWidth == pMovieData->idMovieInfo.width / 2 ) &&
  2174.                 ( wMovieHeight == pMovieData->idMovieInfo.height / 2 ))
  2175.                 wSelectedSize = PLAYER_MOVIE_HALFSIZE;
  2176.             else
  2177.                 wSelectedSize = 0;
  2178.         }
  2179.  
  2180.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_HALFSIZE,
  2181.             ( !pMovieData->bSoundOnly &&
  2182.             ( wSelectedSize == PLAYER_MOVIE_HALFSIZE)) ?
  2183.             MF_CHECKED: MF_UNCHECKED );
  2184.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_NORMALSIZE,
  2185.             ( !pMovieData->bSoundOnly &&
  2186.             ( wSelectedSize == PLAYER_MOVIE_NORMALSIZE)) ?
  2187.             MF_CHECKED: MF_UNCHECKED );
  2188.         CheckMenuItem( hmenuPopup, PLAYER_MOVIE_DOUBLESIZE,
  2189.             ( !pMovieData->bSoundOnly &&
  2190.             ( wSelectedSize == PLAYER_MOVIE_DOUBLESIZE)) ?
  2191.             MF_CHECKED: MF_UNCHECKED );
  2192.  
  2193.         EnableMenuItem( hmenuPopup, PLAYER_MOVIE_SHOWPOSTER,
  2194.             pMovieData->bSoundOnly ? MF_GRAYED: MF_ENABLED );
  2195.     }
  2196.  
  2197.     return 0L;
  2198. }
  2199.  
  2200.  
  2201. // Function: ResizeMovieAndWindow - Resizes the movie and window to the
  2202. //                                  input width and height if flag is TRUE
  2203. //                                  Otherwise resize window to match movie
  2204. // --------------------------------------------------------------------
  2205. // Parameters: HWND         hwndMovie       Handle of Movie window
  2206. //             BOOL         bResizeMovie    TRUE if movie should be resized
  2207. //                                          This will be FALSE when the grow
  2208. //                                          box is used to resize since the
  2209. //                                          movie will already be resized
  2210. //             NPMOVIEDATA  pMovieData      -> to movie data struct
  2211. //             WORD         wMovieWidth     width of movie
  2212. //             WORD         wMovieHeight    height of movie
  2213. //
  2214. // Returns:    LONG         0L if successful
  2215. // --------------------------------------------------------------------
  2216. static LONG NEAR ResizeMovieAndWindow( HWND hwndMovie, BOOL bResizeMovie,
  2217.                NPMOVIEDATA pMovieData, WORD wMovieWidth, WORD wMovieHeight )
  2218.  
  2219. {
  2220.     RECT          rcWindow;     // Window rect
  2221.     RECT          rcWindowPrev; // Prev Window rect
  2222.     RECT          rcBounds;     // Bounds rect
  2223.     POINT         ptCorner;     // Upper-Left corner of window
  2224.     LONG          lError;       // Error return
  2225.     POINT         ptTemp[2];    // Temp array of points
  2226.  
  2227.  
  2228.     if( bResizeMovie &&
  2229.         ( lError = ResizeMovie( pMovieData, wMovieWidth, wMovieHeight )))
  2230.         return lError;
  2231.  
  2232.     // Now Get the bounds rect. In this app, this is the same as the
  2233.     // client rect of the window
  2234.     MCGetControllerBoundsRect( pMovieData->mcMovieController, &rcBounds );
  2235.  
  2236.     // Set about resizing window
  2237.     // Save the prev window rect in client window coordinates
  2238.     GetWindowRect( hwndMovie, &rcWindow );
  2239.     MapWindowPoints( HWND_DESKTOP, PlayerQueryClientWindow(),
  2240.         (LPPOINT) &rcWindow, 2 );
  2241.     rcWindowPrev = rcWindow;
  2242.     ptCorner = *((LPPOINT) &rcWindow );
  2243.  
  2244.     // Adjust corner. This will only happen if window has been
  2245.     // moved using the grow box
  2246.     if( !bResizeMovie && ( rcBounds.left || rcBounds.top )) {
  2247.         ptTemp[0].x = ptTemp[0].y = 0;
  2248.         ptTemp[1] = *((LPPOINT) &rcBounds );
  2249.         MapWindowPoints( hwndMovie, PlayerQueryClientWindow(), ptTemp, 2 );
  2250.  
  2251.         ptCorner.x += ptTemp[1].x - ptTemp[0].x;
  2252.         ptCorner.y += ptTemp[1].y - ptTemp[0].y;
  2253.     }
  2254.  
  2255.     rcWindow = rcBounds;
  2256.     AdjustWindowRect( &rcWindow,
  2257.         GetWindowLong( hwndMovie, GWL_STYLE ), FALSE );
  2258.     // rcWindow contains the new size of the window.
  2259.     // Now offset to the corrent UL corner
  2260.     OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  2261.         ptCorner.y - rcWindow.top );
  2262.  
  2263.     // If window rect has changed, resize after
  2264.     // disabling the WM_SIZE processing
  2265.     if( !EqualRect( &rcWindow, &rcWindowPrev )) {
  2266.         pMovieData->bDisableSizeMsgProcessing = TRUE;
  2267.         MoveWindow( hwndMovie, rcWindow.left, rcWindow.top,
  2268.             rcWindow.right - rcWindow.left,
  2269.             rcWindow.bottom - rcWindow.top, TRUE );
  2270.  
  2271.         // If if happens that after resizing, the movie is smaller than
  2272.         // minimum movie window size, resize movie to fill the window
  2273.         GetClientRect( hwndMovie, &rcWindow );
  2274.         if( !EqualRect( &rcWindow, &rcBounds )) {
  2275.             pMovieData->bSettingControllerSize = TRUE;
  2276.             MCSetControllerBoundsRect
  2277.                 ( pMovieData->mcMovieController, &rcWindow );
  2278.         }
  2279.     }
  2280.  
  2281.     return 0L;
  2282. }
  2283.  
  2284.  
  2285. // Function: ResizeMovie - Resizes the movie to the given size
  2286. // --------------------------------------------------------------------
  2287. // Parameters: NPMOVIEDATA  pMovieData      Pointer to movie data struct
  2288. //             WORD         wMovieWidth     width of movie
  2289. //             WORD         wMovieHeight    height of movie
  2290. //
  2291. // Returns:    LONG         0L if successful
  2292. // --------------------------------------------------------------------
  2293. static LONG NEAR ResizeMovie( NPMOVIEDATA pMovieData,
  2294.                                  WORD wMovieWidth, WORD wMovieHeight )
  2295.  
  2296. {
  2297.     RECT     rcBounds; // Controller bounds rect
  2298.  
  2299.     // set based on input movie dimensions.
  2300.     // Need to add in controller height for bounds rect
  2301.     rcBounds.left = rcBounds.top = 0;
  2302.     rcBounds.right  = wMovieWidth;
  2303.     rcBounds.bottom = wMovieHeight + g.wMovieControllerHeight;
  2304.  
  2305.     pMovieData->bSettingControllerSize = TRUE;
  2306.     MCSetControllerBoundsRect( pMovieData->mcMovieController, &rcBounds );
  2307.  
  2308.     if( pMovieData->hwndGetInfo && !g.bUpdatingInfo ) { // WM_PLAYER_INFO_UPDATE is defined to be in the range WM_COALESCE_FIRST
  2309.                                                         // to WM_COALESCE_LAST which tells Windows to prevent duplicate messages
  2310.                                                         // from appearing in the queue.
  2311.         PostMessage( pMovieData->hwndGetInfo, WM_PLAYER_INFO_UPDATE, 0, 0L );
  2312.     }
  2313.  
  2314.     return 0L;
  2315. }
  2316.  
  2317.  
  2318. // Function: UpdateGBBoundsRect - Updates the grow box bounds rect
  2319. // --------------------------------------------------------------------
  2320. // Parameters: HWND            hwndMovie     Handle of movie window
  2321. //             NPMOVIEDATA     pMovieData    -> movie data struct
  2322. //
  2323. // Returns:    VOID
  2324. // --------------------------------------------------------------------
  2325. static VOID NEAR UpdateGBBoundsRect( HWND hwndMovie, NPMOVIEDATA pMovieData )
  2326.  
  2327. {
  2328.     GetClientRect( PlayerQueryFrameWindow(), &pMovieData->rcGrowBox );
  2329.     MapWindowPoints( PlayerQueryFrameWindow(),
  2330.         hwndMovie, (LPPOINT) &pMovieData->rcGrowBox , 2 );
  2331.     MCDoAction( pMovieData->mcMovieController,
  2332.         mcActionSetGrowBoxBounds, &pMovieData->rcGrowBox );
  2333.  
  2334.     return;
  2335.  
  2336. }
  2337.  
  2338.  
  2339. // Function: MakeAnArialFont - Creates a logical font
  2340. // --------------------------------------------------------------------
  2341. // Parameters: HDC           hdc              Device context
  2342. //             int           nTextSize        Size of font
  2343. //
  2344. // Returns:    HFONT         hFont
  2345. //           Note: It is up to the caller to eventually delete this font
  2346. // --------------------------------------------------------------------
  2347. static HFONT NEAR MakeAnArialFont( HDC hdc, int nTextSize )
  2348.  
  2349. {
  2350.     HFONT       hFont; // Handle to created font
  2351.     PLOGFONT    plf;   // -> to font struct
  2352.  
  2353.     if( !(plf = (PLOGFONT) LocalAlloc( LPTR, sizeof( LOGFONT ))))
  2354.         return NULL;
  2355.  
  2356.     plf->lfHeight         = nTextSize;
  2357.     plf->lfWeight         = FW_LIGHT;
  2358.     plf->lfOutPrecision   = OUT_TT_ONLY_PRECIS;
  2359.     plf->lfPitchAndFamily = FF_SWISS;
  2360.     LoadString( PlayerQueryResources(), PLAYER_STRING_FACENAME,
  2361.         plf->lfFaceName, sizeof( plf->lfFaceName ));
  2362.  
  2363.     hFont = CreateFontIndirect( plf );
  2364.  
  2365.     LocalFree( (LOCALHANDLE) plf );
  2366.  
  2367.     return hFont;
  2368. }
  2369.  
  2370.  
  2371. // Function: InitializeResize - Tests for constrained resize and
  2372. //                              sets dragging rect if true
  2373. // --------------------------------------------------------------------
  2374. // Parameters: HWND          hwndMovie        Handle of movie wnd
  2375. //             NPMOVIEDATA   pMovieData       -> movie data struct
  2376. //             WORD          wHitTestCode     NC hit test code
  2377. //             POINT         ptCursor         Position of cursor in
  2378. //                                            screen coordinates
  2379. //
  2380. // Returns:    WORD          wHitTestCode if in border, else 0
  2381. // --------------------------------------------------------------------
  2382. static WORD NEAR InitializeResize
  2383.           ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2384.                                 WORD wHitTestCode, POINT ptCursor )
  2385.  
  2386. {
  2387.     RECT        rcClipCursor;  // Rect used to clip motion of cursor
  2388.     MINMAXINFO  mmiMinMaxInfo; // Minmax info struct
  2389.  
  2390.  
  2391.     GetWindowRect( hwndMovie, &g.rcResizeRect );
  2392.     GetWindowRect( PlayerQueryClientWindow(), &rcClipCursor );
  2393.  
  2394.     SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  2395.  
  2396.     switch( wHitTestCode ) {
  2397.         case HTTOP:
  2398.             g.ptCursorOffset.x = 0;
  2399.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2400.  
  2401.             rcClipCursor.bottom = g.rcResizeRect.bottom -
  2402.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2403.             break;
  2404.         case HTBOTTOM:
  2405.             g.ptCursorOffset.x = 0;
  2406.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2407.  
  2408.             rcClipCursor.top = g.rcResizeRect.top +
  2409.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2410.             break;
  2411.         case HTLEFT:
  2412.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2413.             g.ptCursorOffset.y = 0;
  2414.  
  2415.             rcClipCursor.right = g.rcResizeRect.right -
  2416.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2417.             break;
  2418.         case HTRIGHT:
  2419.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2420.             g.ptCursorOffset.y = 0;
  2421.  
  2422.             rcClipCursor.left = g.rcResizeRect.left +
  2423.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2424.             break;
  2425.         case HTTOPLEFT:
  2426.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2427.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2428.  
  2429.             rcClipCursor.right  = g.rcResizeRect.right -
  2430.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2431.             if( !pMovieData->bSoundOnly )
  2432.                 rcClipCursor.bottom = g.rcResizeRect.bottom -
  2433.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2434.             break;
  2435.         case HTBOTTOMRIGHT:
  2436.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2437.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2438.  
  2439.             rcClipCursor.left = g.rcResizeRect.left +
  2440.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2441.             if( !pMovieData->bSoundOnly )
  2442.                 rcClipCursor.top  = g.rcResizeRect.top +
  2443.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2444.             break;
  2445.         case HTTOPRIGHT:
  2446.             g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
  2447.             g.ptCursorOffset.y = g.rcResizeRect.top - ptCursor.y;
  2448.  
  2449.             rcClipCursor.left   = g.rcResizeRect.left +
  2450.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2451.             if( !pMovieData->bSoundOnly )
  2452.                 rcClipCursor.bottom = g.rcResizeRect.bottom -
  2453.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2454.             break;
  2455.         case HTBOTTOMLEFT:
  2456.             g.ptCursorOffset.x = g.rcResizeRect.left - ptCursor.x;
  2457.             g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  2458.  
  2459.             rcClipCursor.right = g.rcResizeRect.right -
  2460.                 mmiMinMaxInfo.ptMinTrackSize.x;
  2461.             if( !pMovieData->bSoundOnly )
  2462.                 rcClipCursor.top   = g.rcResizeRect.top +
  2463.                 mmiMinMaxInfo.ptMinTrackSize.y;
  2464.             break;
  2465.  
  2466.         default:
  2467.             return 0;
  2468.     }
  2469.  
  2470.  
  2471.     if( pMovieData->bSoundOnly ) {
  2472.         SetCursor( g.hcursor = LoadCursor( NULL, IDC_SIZEWE ));
  2473.     }
  2474.     else {
  2475.         SetCursor( g.hcursor = SetCursor( NULL ));
  2476.     }
  2477.     ClipCursor( &rcClipCursor );
  2478.  
  2479.     g.wScaleWidth  = max( pMovieData->idMovieInfo.width / 2, 1 );
  2480.     g.wScaleHeight = max( pMovieData->idMovieInfo.height / 2, 1 );
  2481.  
  2482.     return wHitTestCode;
  2483. }
  2484.  
  2485.  
  2486. // Function: MoveTheMovieResizeRect - Moves the resizing frame
  2487. // --------------------------------------------------------------------
  2488. // Parameters: HWND          hwndMovie       Handle of movie window
  2489. //             NPMOVIEDATA   pMovieData      -> movie data struct
  2490. //             WORD          wHitTestCode    Hit test code
  2491. //             POINT         ptCursor        Current cursor position in
  2492. //                                           screen coordinates
  2493. //             BOOL          bStarting       TRUE if this is the first
  2494. //                                           call of a drag
  2495. //
  2496. // Returns:    VOID
  2497. // --------------------------------------------------------------------
  2498. static VOID NEAR MoveTheMovieResizeRect
  2499.          ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2500.                 WORD wHitTestCode, POINT ptCursor, BOOL bStarting )
  2501.  
  2502. {
  2503.     RECT     rcNewRect;    // resize rect in screen coordinates
  2504.     WORD     wMovieWidth;  // Movie width
  2505.     WORD     wMovieHeight; // Movie height
  2506.  
  2507.     ptCursor.x += g.ptCursorOffset.x;
  2508.     ptCursor.y += g.ptCursorOffset.y;
  2509.  
  2510.     rcNewRect = g.rcResizeRect;
  2511.     switch( wHitTestCode ) {
  2512.         case HTTOP:
  2513.             if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2514.                 rcNewRect.top = ptCursor.y;
  2515.             }
  2516.             else {
  2517.                 wMovieHeight = rcNewRect.bottom - ptCursor.y -
  2518.                     g.wTopAndBottom;
  2519.                 if( ISKEYDOWN( VK_CONTROL )) {
  2520.                     wMovieHeight = g.wScaleHeight *
  2521.                         max( wMovieHeight / g.wScaleHeight, 1 );
  2522.  
  2523.                     if( abs( wMovieHeight -
  2524.                         pMovieData->idMovieInfo.height ) <= 2 ) {
  2525.                         wMovieWidth  = pMovieData->idMovieInfo.width;
  2526.                         wMovieHeight = pMovieData->idMovieInfo.height;
  2527.                     }
  2528.                     else {
  2529.                         wMovieWidth = MulDiv( wMovieHeight,
  2530.                             pMovieData->idMovieInfo.width,
  2531.                             pMovieData->idMovieInfo.height );
  2532.                     }
  2533.                 }
  2534.                 else {
  2535.                     wMovieWidth = MulDiv( wMovieHeight,
  2536.                         pMovieData->idMovieInfo.width,
  2537.                         pMovieData->idMovieInfo.height );
  2538.                 }
  2539.  
  2540.                 rcNewRect.right = rcNewRect.left + g.wSides + wMovieWidth;
  2541.                 rcNewRect.top   = rcNewRect.bottom -
  2542.                     g.wTopAndBottom - wMovieHeight;
  2543.             }
  2544.             break;
  2545.         case HTBOTTOM:
  2546.             if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2547.                 rcNewRect.bottom = ptCursor.y;
  2548.             }
  2549.             else {
  2550.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2551.                 if( ISKEYDOWN( VK_CONTROL )) {
  2552.                     wMovieHeight = g.wScaleHeight *
  2553.                         max( wMovieHeight / g.wScaleHeight, 1 );
  2554.                     if( abs( wMovieHeight -
  2555.                         pMovieData->idMovieInfo.height ) <= 2 ) {
  2556.                         wMovieWidth  = pMovieData->idMovieInfo.width;
  2557.                         wMovieHeight = pMovieData->idMovieInfo.height;
  2558.                     }
  2559.                     else {
  2560.                         wMovieWidth = MulDiv( wMovieHeight,
  2561.                             pMovieData->idMovieInfo.width,
  2562.                             pMovieData->idMovieInfo.height );
  2563.                     }
  2564.                 }
  2565.                 else {
  2566.                     wMovieWidth = MulDiv( wMovieHeight,
  2567.                         pMovieData->idMovieInfo.width,
  2568.                         pMovieData->idMovieInfo.height );
  2569.                 }
  2570.  
  2571.                 rcNewRect.right  = rcNewRect.left + g.wSides + wMovieWidth;
  2572.                 rcNewRect.bottom = rcNewRect.top +
  2573.                     g.wTopAndBottom + wMovieHeight;
  2574.             }
  2575.             break;
  2576.         case HTLEFT:
  2577.             if( pMovieData->bSoundOnly ||
  2578.                 ( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT ))) {
  2579.                 rcNewRect.left = ptCursor.x;
  2580.             }
  2581.             else {
  2582.                 wMovieWidth = rcNewRect.right - ptCursor.x - g.wSides;
  2583.                 if( ISKEYDOWN( VK_CONTROL )) {
  2584.                     wMovieWidth = g.wScaleWidth *
  2585.                         max( wMovieWidth / g.wScaleWidth, 1 );
  2586.                     if( abs( wMovieWidth -
  2587.                         pMovieData->idMovieInfo.width ) <= 2 ) {
  2588.                         wMovieWidth  = pMovieData->idMovieInfo.width;
  2589.                         wMovieHeight = pMovieData->idMovieInfo.height;
  2590.                     }
  2591.                     else {
  2592.                         wMovieHeight = MulDiv( wMovieWidth,
  2593.                             pMovieData->idMovieInfo.height,
  2594.                             pMovieData->idMovieInfo.width );
  2595.                     }
  2596.                 }
  2597.                 else {
  2598.                     wMovieHeight = MulDiv( wMovieWidth,
  2599.                         pMovieData->idMovieInfo.height,
  2600.                         pMovieData->idMovieInfo.width );
  2601.                 }
  2602.  
  2603.                 rcNewRect.left   = rcNewRect.right - g.wSides - wMovieWidth;
  2604.                 rcNewRect.bottom = rcNewRect.top +
  2605.                     g.wTopAndBottom + wMovieHeight;
  2606.             }
  2607.             break;
  2608.         case HTRIGHT:
  2609.             if( pMovieData->bSoundOnly ||
  2610.                 ( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT ))) {
  2611.                 rcNewRect.right = ptCursor.x;
  2612.             }
  2613.             else {
  2614.                 wMovieWidth = ptCursor.x - rcNewRect.left - g.wSides;
  2615.                 if( ISKEYDOWN( VK_CONTROL )) {
  2616.                     wMovieWidth = g.wScaleWidth *
  2617.                         max( wMovieWidth / g.wScaleWidth, 1 );
  2618.                     if( abs( wMovieWidth -
  2619.                         pMovieData->idMovieInfo.width ) <= 2 ) {
  2620.                         wMovieWidth  = pMovieData->idMovieInfo.width;
  2621.                         wMovieHeight = pMovieData->idMovieInfo.height;
  2622.                     }
  2623.                     else {
  2624.                         wMovieHeight = MulDiv( wMovieWidth,
  2625.                             pMovieData->idMovieInfo.height,
  2626.                             pMovieData->idMovieInfo.width );
  2627.                     }
  2628.                 }
  2629.                 else {
  2630.                     wMovieHeight = MulDiv( wMovieWidth,
  2631.                         pMovieData->idMovieInfo.height,
  2632.                         pMovieData->idMovieInfo.width );
  2633.                 }
  2634.  
  2635.                 rcNewRect.right  = rcNewRect.left + g.wSides + wMovieWidth;
  2636.                 rcNewRect.bottom = rcNewRect.top +
  2637.                     g.wTopAndBottom + wMovieHeight;
  2638.             }
  2639.             break;
  2640.         case HTTOPLEFT:
  2641.             if( pMovieData->bSoundOnly ) {
  2642.                 rcNewRect.left = ptCursor.x;
  2643.             }
  2644.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2645.                 *((LPPOINT) &rcNewRect.left) = ptCursor;
  2646.             }
  2647.             else {
  2648.                 wMovieWidth  = rcNewRect.right - ptCursor.x - g.wSides;
  2649.                 wMovieHeight = rcNewRect.bottom - ptCursor.y -
  2650.                     g.wTopAndBottom;
  2651.                 GetProportionalDimensions( pMovieData,
  2652.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2653.                 rcNewRect.top = rcNewRect.bottom - wMovieHeight -
  2654.                     g.wTopAndBottom;
  2655.                 rcNewRect.left = rcNewRect.right - wMovieWidth - g.wSides;
  2656.             }
  2657.             break;
  2658.         case HTBOTTOMRIGHT:
  2659.             if( pMovieData->bSoundOnly ) {
  2660.                 rcNewRect.right = ptCursor.x;
  2661.             }
  2662.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2663.                 *((LPPOINT) &rcNewRect.right) = ptCursor;
  2664.             }
  2665.             else {
  2666.                 wMovieWidth  = ptCursor.x - rcNewRect.left - g.wSides;
  2667.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2668.                 GetProportionalDimensions( pMovieData,
  2669.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2670.                 rcNewRect.bottom = rcNewRect.top + wMovieHeight +
  2671.                     g.wTopAndBottom;
  2672.                 rcNewRect.right = rcNewRect.left + wMovieWidth + g.wSides;
  2673.             }
  2674.             break;
  2675.         case HTTOPRIGHT:
  2676.             if( pMovieData->bSoundOnly ) {
  2677.                 rcNewRect.right = ptCursor.x;
  2678.             }
  2679.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2680.                 rcNewRect.right = ptCursor.x;
  2681.                 rcNewRect.top   = ptCursor.y;
  2682.             }
  2683.             else {
  2684.                 wMovieWidth  = ptCursor.x - rcNewRect.left - g.wSides;
  2685.                 wMovieHeight = rcNewRect.bottom -
  2686.                     ptCursor.y - g.wTopAndBottom;
  2687.                 GetProportionalDimensions( pMovieData,
  2688.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2689.                 rcNewRect.top = rcNewRect.bottom - wMovieHeight -
  2690.                     g.wTopAndBottom;
  2691.                 rcNewRect.right = rcNewRect.left + wMovieWidth + g.wSides;
  2692.             }
  2693.             break;
  2694.         case HTBOTTOMLEFT:
  2695.             if( pMovieData->bSoundOnly ) {
  2696.                 rcNewRect.left = ptCursor.x;
  2697.             }
  2698.             else if( !ISKEYDOWN( VK_CONTROL ) && !ISKEYDOWN( VK_SHIFT )) {
  2699.                 rcNewRect.left   = ptCursor.x;
  2700.                 rcNewRect.bottom = ptCursor.y;
  2701.             }
  2702.             else {
  2703.                 wMovieWidth  = rcNewRect.right - ptCursor.x - g.wSides;
  2704.                 wMovieHeight = ptCursor.y - rcNewRect.top - g.wTopAndBottom;
  2705.                 GetProportionalDimensions( pMovieData,
  2706.                     &wMovieWidth, &wMovieHeight, ISKEYDOWN( VK_CONTROL ));
  2707.                 rcNewRect.bottom = rcNewRect.top + wMovieHeight +
  2708.                     g.wTopAndBottom;
  2709.                 rcNewRect.left = rcNewRect.right - wMovieWidth - g.wSides;
  2710.             }
  2711.             break;
  2712.     }
  2713.  
  2714.     if( bStarting ) {
  2715.         g.rcResizeRect = rcNewRect;
  2716.         g.bFatResizeBorder = IsNormalSize( &g.rcResizeRect, pMovieData );
  2717.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2718.     }
  2719.     else if( !EqualRect( &g.rcResizeRect, &rcNewRect )) {
  2720.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2721.         g.rcResizeRect = rcNewRect;
  2722.         g.bFatResizeBorder = IsNormalSize( &g.rcResizeRect, pMovieData );
  2723.         DrawTheFrameRect( &g.rcResizeRect, g.bFatResizeBorder );
  2724.     }
  2725.  
  2726.     return;
  2727. }
  2728.  
  2729.  
  2730. // Function: AdjustForMinProportionalSize - Adjusts the final dimensions of a movie
  2731. //                                          when a dimension is less than a minimum
  2732. //                                          allowed size
  2733. // --------------------------------------------------------------------
  2734. // Parameters: HWND             hwndMovie      Handle of movie wnd
  2735. //             NPMOVIEDATA      pMovieData     -> movie data struct
  2736. //             LPWORD           lpwWidth;      -> window width
  2737. //             LPWORD           lpwHeight;     -> window height
  2738. //             BOOL             bCtrlKeyDown   TRUE if CONTROL key is down
  2739. //
  2740. // Returns:    VOID
  2741. // --------------------------------------------------------------------
  2742. static VOID NEAR AdjustForMinProportionalSize
  2743.           ( HWND hwndMovie, NPMOVIEDATA pMovieData,
  2744.                  LPWORD lpwWidth, LPWORD lpwHeight, BOOL bCtrlKeyDown )
  2745.  
  2746. {
  2747.     MINMAXINFO  mmiMinMaxInfo; // Minmax info struct
  2748.     WORD        wMovieWidth;   // Movie width
  2749.     WORD        wMovieHeight;  // Movie height
  2750.  
  2751.  
  2752.     SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  2753.     // Add resizing borders
  2754.     mmiMinMaxInfo.ptMinTrackSize.x += g.wSides;
  2755.     mmiMinMaxInfo.ptMinTrackSize.y += g.wTBBorder;
  2756.  
  2757.     if( ( *lpwWidth > (WORD) mmiMinMaxInfo.ptMinTrackSize.x ) &&
  2758.         ( *lpwHeight > (WORD) mmiMinMaxInfo.ptMinTrackSize.y ))
  2759.         return;
  2760.  
  2761.     if( *lpwWidth < (WORD) mmiMinMaxInfo.ptMinTrackSize.x ) {
  2762.         *lpwWidth = mmiMinMaxInfo.ptMinTrackSize.x;
  2763.     }
  2764.     if( *lpwHeight < (WORD) mmiMinMaxInfo.ptMinTrackSize.y ) {
  2765.         *lpwHeight = mmiMinMaxInfo.ptMinTrackSize.y;
  2766.     }
  2767.  
  2768.     // Mult by 10 because numbers may be small
  2769.     wMovieWidth  = ( *lpwWidth - g.wSides ) * 10;
  2770.     wMovieHeight = ( *lpwHeight - g.wTopAndBottom ) * 10;
  2771.     GetProportionalDimensions
  2772.         ( pMovieData, &wMovieWidth, &wMovieHeight, bCtrlKeyDown );
  2773.     *lpwWidth  = ( wMovieWidth + 10 * g.wSides ) / 10;
  2774.     *lpwHeight = ( wMovieHeight + 10 * g.wTopAndBottom ) / 10;
  2775.  
  2776.     return;
  2777.  
  2778. }
  2779.  
  2780.  
  2781. // Function: GetProportionalDimensions - Scales the dimensions of a movie to
  2782. //                                       be in the same proportions as the
  2783. //                                       original movie dimensions
  2784. // --------------------------------------------------------------------
  2785. // Parameters: NPMOVIEDATA    pMovieData        -> movie data struct
  2786. //             PWORD          pwMovieWidth      -> current width
  2787. //             PWORD          pwMovieHeight     -> current height
  2788. //             BOOL           bCtrlKeyDown      TRUE if CONTROL key is down
  2789. //
  2790. // Returns:    VOID
  2791. // --------------------------------------------------------------------
  2792. static VOID NEAR GetProportionalDimensions
  2793.       ( NPMOVIEDATA pMovieData, PWORD pwMovieWidth,
  2794.                                 PWORD pwMovieHeight, BOOL bCtrlKeyDown )
  2795.  
  2796. {
  2797.     WORD     wTempHeight; // Temp height
  2798.  
  2799.     wTempHeight = MulDiv( *pwMovieWidth,
  2800.         pMovieData->idMovieInfo.height,
  2801.         pMovieData->idMovieInfo.width );
  2802.     if( wTempHeight >= *pwMovieHeight ) {
  2803.         *pwMovieHeight = wTempHeight;
  2804.     }
  2805.     else {
  2806.         *pwMovieWidth = MulDiv( *pwMovieHeight,
  2807.             pMovieData->idMovieInfo.width,
  2808.             pMovieData->idMovieInfo.height );
  2809.     }
  2810.  
  2811.     if( bCtrlKeyDown ) {
  2812.         *pwMovieHeight = g.wScaleHeight *
  2813.             max( *pwMovieHeight / g.wScaleHeight, 1 );
  2814.  
  2815.         if( abs( *pwMovieHeight - pMovieData->idMovieInfo.height ) <= 2 ) {
  2816.             *pwMovieWidth  = pMovieData->idMovieInfo.width;
  2817.             *pwMovieHeight = pMovieData->idMovieInfo.height;
  2818.         }
  2819.         else {
  2820.             *pwMovieWidth = MulDiv( *pwMovieHeight,
  2821.                 pMovieData->idMovieInfo.width,
  2822.                 pMovieData->idMovieInfo.height );
  2823.         }
  2824.     }
  2825.  
  2826.     return;
  2827. }
  2828.  
  2829.  
  2830. // Function: IsNormalSize - Determines if movie is normal size
  2831. // --------------------------------------------------------------------
  2832. // Parameters: RECT          lprcResizeRect   -> resize rect
  2833. //             NPMOVIEDATA   pMovieData       -> movie data struct
  2834. //
  2835. // Returns:    BOOL     TRUE if input rect has the normal movie dimensions
  2836. // --------------------------------------------------------------------
  2837. static BOOL NEAR IsNormalSize
  2838.                    ( LPRECT lprcResizeRect, NPMOVIEDATA pMovieData )
  2839.  
  2840. {
  2841.     WORD    wMovieWidth;  // Current width of movie
  2842.     WORD    wMovieHeight; // Current height of movie
  2843.  
  2844.     wMovieWidth = lprcResizeRect->right -
  2845.         lprcResizeRect->left - g.wSides;
  2846.     wMovieHeight = lprcResizeRect->bottom -
  2847.         lprcResizeRect->top - g.wTopAndBottom;
  2848.  
  2849.     return ( wMovieWidth == pMovieData->idMovieInfo.width ) &&
  2850.         ( wMovieHeight == pMovieData->idMovieInfo.height );
  2851. }
  2852.  
  2853.  
  2854. // Function: DrawTheFrameRect - Draws the resizing frame
  2855. // --------------------------------------------------------------------
  2856. // Parameters: RECT      lprcResizeRect     -> resize rect
  2857. //             BOOL      bFatBorder         Flag to draw thicker border
  2858. //
  2859. // Returns:    VOID
  2860. // --------------------------------------------------------------------
  2861. static VOID NEAR DrawTheFrameRect( LPRECT lprcResizeRect, BOOL bFatBorder )
  2862.  
  2863. {
  2864.     HDC            hdc;             // DC of desktop
  2865.     HBRUSH         hbrushSave;      // Prev brush
  2866.     HBITMAP        hbitmapCheckers; // Handle of checkerboard bitmap
  2867.     WORD           wWBorder;        // Width of vertical border
  2868.     WORD           wHBorder;        // Width of horizontal border
  2869.  
  2870.  
  2871.     typedef  BOOL ( CALLBACK* FFRAMEPROC ) (HDC, LPRECT, int, int, DWORD);
  2872.  
  2873.     static  WORD   wBorderWidth;             // Width of vertical resize border
  2874.     static  WORD   wBorderHeight;            // Height of horizontal resize border
  2875.     static  FFRAMEPROC  lpfnFastWindowFrame; // -> FastWindowFrame()
  2876.     static  HBRUSH  hbrushCheckers;          // Handle to frame brush
  2877.  
  2878.     // FastWindowFrame() is an undocumented Windows function
  2879.     // described in "Undocumented Windows" by Andrew Schulman,
  2880.     // David Maxey and Matt Pietrek, Addison Wesley, 1992.
  2881.  
  2882.     if( lprcResizeRect == NULL ) // Clean up
  2883.     {
  2884.         if( hbrushCheckers ) {
  2885.             DeleteObject( hbrushCheckers );
  2886.             hbrushCheckers = NULL;
  2887.         }
  2888.         return;
  2889.     }
  2890.  
  2891.     if( !lpfnFastWindowFrame ) {
  2892.         lpfnFastWindowFrame = (FFRAMEPROC) GetProcAddress(
  2893.             GetModuleHandle( "GDI" ), "FASTWINDOWFRAME" );
  2894.         wBorderWidth  = GetSystemMetrics( SM_CXFRAME ) - 1;
  2895.         wBorderHeight = GetSystemMetrics( SM_CXFRAME ) - 1;
  2896.     }
  2897.  
  2898.     if( !hbrushCheckers &&
  2899.         ( hbitmapCheckers = LoadBitmap( PlayerQueryInstance(),
  2900.         MAKEINTRESOURCE( PLAYER_CHECKERS_BITMAP )))) {
  2901.         hbrushCheckers = CreatePatternBrush( hbitmapCheckers );
  2902.         DeleteObject( hbitmapCheckers );
  2903.     }
  2904.  
  2905.     if( hdc = GetDC( NULL )) {
  2906.         if( lpfnFastWindowFrame ) {
  2907.             if( hbrushCheckers )
  2908.                 hbrushSave = SelectObject( hdc, hbrushCheckers );
  2909.             else
  2910.                 hbrushSave = SelectObject( hdc,
  2911.                 GetStockObject( GRAY_BRUSH ));
  2912.  
  2913.             wWBorder = wBorderWidth  + ( bFatBorder? 2: 0);
  2914.             wHBorder = wBorderHeight + ( bFatBorder? 2: 0);
  2915.  
  2916.             if( !( *lpfnFastWindowFrame ) ( hdc, lprcResizeRect,
  2917.                 wWBorder, wHBorder, PATINVERT )) { // Use PatBlt when FastWindowFrame fails
  2918.                 ExcludeClipRect( hdc,
  2919.                     lprcResizeRect->left + wWBorder,
  2920.                     lprcResizeRect->top  + wHBorder,
  2921.                     lprcResizeRect->right  - wWBorder,
  2922.                     lprcResizeRect->bottom - wHBorder );
  2923.  
  2924.                 PatBlt( hdc, lprcResizeRect->left,
  2925.                     lprcResizeRect->top,
  2926.                     lprcResizeRect->right - lprcResizeRect->left,
  2927.                     lprcResizeRect->bottom - lprcResizeRect->top,
  2928.                     PATINVERT );
  2929.             }
  2930.  
  2931.             if( hbrushSave )
  2932.                 SelectObject( hdc, hbrushSave );
  2933.         }
  2934.         else {
  2935.             DrawFocusRect( hdc, lprcResizeRect );
  2936.         }
  2937.  
  2938.         ReleaseDC( NULL, hdc );
  2939.     }
  2940.  
  2941.     return;
  2942. }
  2943.  
  2944.  
  2945. // Function: SubclassTheGrowBox - Subclass the movie controller grow box
  2946. // --------------------------------------------------------------------
  2947. // Parameters: HWND           hwndMovie    Handle of movie wnd
  2948. //             NPMOVIEDATA    pMovieData   -> movie data struct
  2949. //
  2950. // Returns:    BOOL    TRUE if successful
  2951. // --------------------------------------------------------------------
  2952. static BOOL NEAR SubclassTheGrowBox
  2953.                               ( HWND hwndMovie, NPMOVIEDATA pMovieData )
  2954.  
  2955. {
  2956.     WNDENUMPROC     lpfnEnumProc; // -> enumeration proc
  2957.  
  2958.     if( lpfnEnumProc = (WNDENUMPROC) MakeProcInstance
  2959.         ( (FARPROC) MovieChildEnumProc, PlayerQueryInstance())) {
  2960.         EnumChildWindows( hwndMovie, lpfnEnumProc,
  2961.             MAKELONG( pMovieData, 0 ));
  2962.         FreeProcInstance( (FARPROC) lpfnEnumProc );
  2963.  
  2964.         return pMovieData->bGrowBoxSubclassed;
  2965.     }
  2966.  
  2967.     return FALSE;
  2968. }
  2969.  
  2970.  
  2971. // Function: MovieChildEnumProc - Movie child enumeration proc
  2972. // --------------------------------------------------------------------
  2973. // Parameters: As required by Microsoft Windows
  2974. //
  2975. // Returns:    As required by Microsoft Windows
  2976. // --------------------------------------------------------------------
  2977. BOOL __export CALLBACK MovieChildEnumProc
  2978.                               ( HWND hwndChild, LPARAM lParam )
  2979.  
  2980. {
  2981.     char      szClassName[50]; // Class name buffer
  2982.  
  2983.     // The grow box class name can be found by using the enumeration
  2984.     // routine to list all the names
  2985.     #define GROWBOXCLASSNAME   "MCGrowBox"
  2986.  
  2987.     if( GetClassName( hwndChild,
  2988.         szClassName, sizeof( szClassName )) &&
  2989.         !lstrcmpi( GROWBOXCLASSNAME, szClassName )) {
  2990.         if( g.lpNewGBProc ||
  2991.             ( g.lpNewGBProc = (WNDPROC) MakeProcInstance
  2992.             ( (FARPROC) GBSubClassProc, PlayerQueryInstance()))) {
  2993.             if( g.lpOldGBProc = (WNDPROC) SetWindowLong
  2994.                 ( hwndChild, GWL_WNDPROC, (LONG) g.lpNewGBProc )) {
  2995.                 ((NPMOVIEDATA) LOWORD( lParam ))->
  2996.                     bGrowBoxSubclassed = TRUE;
  2997.             }
  2998.         }
  2999.  
  3000.         return FALSE;
  3001.     }
  3002.  
  3003.     return TRUE;
  3004. }
  3005.  
  3006.  
  3007. // Function: GBSubClassProc - Movie controller grow box subclass
  3008. // --------------------------------------------------------------------
  3009. // Parameters: As required by Microsoft Windows
  3010. //
  3011. // Returns:    As required by Microsoft Windows
  3012. // --------------------------------------------------------------------
  3013. LONG __export CALLBACK GBSubClassProc
  3014.     ( HWND hwndGrowBox, UINT message, WPARAM wParam, LPARAM lParam )
  3015.  
  3016. {
  3017.     POINT    ptCursor; // Cursor position
  3018.  
  3019.     if( g.hwndMaximizedMovie && ( message == WM_LBUTTONDOWN )) {
  3020.         ptCursor = MAKEPOINT( lParam );
  3021.         ClientToScreen( hwndGrowBox, &ptCursor );
  3022.         InitMaxWndGrowBoxResize( hwndGrowBox, ptCursor );
  3023.  
  3024.         SetCapture( g.hwndMaximizedMovie );
  3025.         g.bCapturedGrowBox = TRUE;
  3026.  
  3027.         return 0L;
  3028.     }
  3029.  
  3030.     return CallWindowProc
  3031.         ( g.lpOldGBProc, hwndGrowBox, message, wParam, lParam );
  3032. }
  3033.  
  3034.  
  3035. // Function: InitMaxWndGrowBoxResize - Initializes the maximized window grow
  3036. //                                     box resizing
  3037. // --------------------------------------------------------------------
  3038. // Parameters: HWND        hwndGrowBox    Handle of grow box
  3039. //             POINT       ptCursor       Position of cursor in screen coords.
  3040. //
  3041. // Returns:    BOOL        TRUE if successful
  3042. // --------------------------------------------------------------------
  3043. static BOOL NEAR InitMaxWndGrowBoxResize
  3044.                               ( HWND hwndGrowBox, POINT ptCursor )
  3045.  
  3046. {
  3047.     RECT         rcClipCursor; // Clip cursor rect
  3048.     HDC          hdc;          // DC of desktop
  3049.  
  3050.     GetWindowRect( PlayerQueryFrameWindow(), &g.rcResizeRect );
  3051.     g.ptCursorOffset.x = g.rcResizeRect.right  - ptCursor.x;
  3052.     g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
  3053.  
  3054.     rcClipCursor.left = g.rcResizeRect.left +
  3055.         GetSystemMetrics( SM_CXMINTRACK ) - g.ptCursorOffset.x;
  3056.     rcClipCursor.top  = g.rcResizeRect.top +
  3057.         GetSystemMetrics( SM_CYMINTRACK ) - g.ptCursorOffset.y;
  3058.  
  3059.     // Offset the clip cursor rect to keep frame on screen
  3060.     if( hdc = GetDC( NULL )) {
  3061.         rcClipCursor.right =
  3062.             GetDeviceCaps( hdc, HORZRES ) - g.ptCursorOffset.x;
  3063.         rcClipCursor.bottom =
  3064.             GetDeviceCaps( hdc, VERTRES ) - g.ptCursorOffset.y;
  3065.         ReleaseDC( NULL, hdc );
  3066.     }
  3067.     else {
  3068.         rcClipCursor.right  = 0x7fff;
  3069.         rcClipCursor.bottom = 0x7fff;
  3070.     }
  3071.     ClipCursor( &rcClipCursor );
  3072.  
  3073.     DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3074.  
  3075.     return TRUE;
  3076. }
  3077.  
  3078.  
  3079. // Function: MoveTheFrameResizeRect - Moves the resizing frame during
  3080. //                                    maximized wnd grow box resizing
  3081. // --------------------------------------------------------------------
  3082. // Parameters: HWND          hwndMovie     Handle of movie wnd
  3083. //             POINT         ptCursor      Current cursor position in
  3084. //                                         screen coordinates
  3085. //
  3086. // Returns:    VOID
  3087. // --------------------------------------------------------------------
  3088. static VOID NEAR MoveTheFrameResizeRect
  3089.                           ( HWND hwndMovie, POINT ptCursor )
  3090.  
  3091. {
  3092.     RECT     rcNewRect; // resize rect in screen coordinates
  3093.  
  3094.     ptCursor.x += g.ptCursorOffset.x;
  3095.     ptCursor.y += g.ptCursorOffset.y;
  3096.  
  3097.     rcNewRect = g.rcResizeRect;
  3098.     *((LPPOINT) &rcNewRect.right) = ptCursor;
  3099.  
  3100.     if( !EqualRect( &g.rcResizeRect, &rcNewRect )) {
  3101.         DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3102.         g.rcResizeRect = rcNewRect;
  3103.         DrawTheFrameRect( &g.rcResizeRect, FALSE );
  3104.     }
  3105.  
  3106.     return;
  3107. }
  3108.  
  3109.  
  3110. // Function: FixUpMovieTiling - Sets the dimensions of the movie
  3111. //                              window when tiling
  3112. // --------------------------------------------------------------------
  3113. // Parameters: HWND             hwndMovie      Handle of movie wnd
  3114. //             NPMOVIEDATA      pMovieData     -> movie data struct
  3115. //             LPWINDOWPOS      lpwpWndPos     -> WINDOWPOS struct
  3116. //
  3117. // Returns:    LONG      Always 0L
  3118. // --------------------------------------------------------------------
  3119. static LONG NEAR FixUpMovieTiling
  3120.      ( HWND hwndMovie, NPMOVIEDATA pMovieData, LPWINDOWPOS lpwpWndPos )
  3121.  
  3122. {
  3123.     WORD          wMovieWidthMDI;  // Width of tile region
  3124.     WORD          wMovieHeightMDI; // Height of tile region
  3125.     WORD          wTemp;           // Temp
  3126.     MINMAXINFO    mmiMinMaxInfo;   // MinMax info struct
  3127.  
  3128.  
  3129.     if( pMovieData->bSoundOnly ) {
  3130.         SetMinMaxInfo( hwndMovie, pMovieData, &mmiMinMaxInfo );
  3131.         lpwpWndPos->cx =
  3132.             max( mmiMinMaxInfo.ptMinTrackSize.x,
  3133.             min( (int) g.wSoundOnlyDefWidth, lpwpWndPos->cx ));
  3134.         lpwpWndPos->cy = mmiMinMaxInfo.ptMaxTrackSize.y;
  3135.  
  3136.         return 0L;
  3137.     }
  3138.  
  3139.     wMovieWidthMDI  = lpwpWndPos->cx - g.wSides;
  3140.     wMovieHeightMDI = lpwpWndPos->cy - g.wTopAndBottom;
  3141.  
  3142.     if( ( wMovieWidthMDI >= pMovieData->idMovieInfo.width ) &&
  3143.         ( wMovieHeightMDI >= pMovieData->idMovieInfo.height )) {
  3144.         lpwpWndPos->cx = pMovieData->idMovieInfo.width + g.wSides;
  3145.         lpwpWndPos->cy = pMovieData->idMovieInfo.height +
  3146.             g.wTopAndBottom;
  3147.     }
  3148.     else // Try setting height and calc width
  3149.     {
  3150.         wTemp = MulDiv( wMovieHeightMDI,
  3151.             pMovieData->idMovieInfo.width,
  3152.             pMovieData->idMovieInfo.height );
  3153.         // If it fits, we are done
  3154.         if( wTemp <= wMovieWidthMDI ) {
  3155.             lpwpWndPos->cx = wTemp + g.wSides;
  3156.         }
  3157.         else // Set width and calc height
  3158.         {
  3159.             wTemp = MulDiv( wMovieWidthMDI,
  3160.                 pMovieData->idMovieInfo.height,
  3161.                 pMovieData->idMovieInfo.width );
  3162.             lpwpWndPos->cy = wTemp + g.wTopAndBottom;
  3163.         }
  3164.  
  3165.         // Now check for min allowed proportional size
  3166.         AdjustForMinProportionalSize( hwndMovie, pMovieData,
  3167.             &lpwpWndPos->cx, &lpwpWndPos->cy, FALSE );
  3168.     }
  3169.  
  3170.     return 0L;
  3171. }
  3172.  
  3173.  
  3174. // Function: SetOptionsDefaults - Set option defaults
  3175. // --------------------------------------------------------------------
  3176. // Parameters: HWND             hwndMovie      Movie hwnd
  3177. //             NPMOVIEDATA      pMovieData     -> movie data struct
  3178. //
  3179. // Returns:    VOID
  3180. // --------------------------------------------------------------------
  3181. static VOID NEAR SetOptionsDefaults
  3182.                               ( HWND hwndMovie, NPMOVIEDATA pMovieData )
  3183.  
  3184. { // Preset copy struct parameters that do not change
  3185.     pMovieData->qtoleOptions.lStructSize     = sizeof( QTOLE_OPTIONSMOVIE );
  3186.     pMovieData->qtoleOptions.lVersion        = VERSION_1;
  3187.     pMovieData->qtoleOptions.wObjectType     = MOVIE_OBJECT;
  3188.     pMovieData->qtoleOptions.hwndObject      = hwndMovie;
  3189.  
  3190.     pMovieData->qtoleOptions.mMovie          = pMovieData->mMovie;
  3191.     pMovieData->qtoleOptions.bSoundOnlyMovie = pMovieData->bSoundOnly;
  3192.     pMovieData->qtoleOptions.lfxRate         = DEFAULT_RATE;
  3193.  
  3194.     pMovieData->qtoleOptions.sizeNormal.cx   = pMovieData->idMovieInfo.width;
  3195.     pMovieData->qtoleOptions.sizeNormal.cy   = pMovieData->idMovieInfo.height;
  3196.  
  3197.     pMovieData->qtoleOptions.tvMovieDuration =
  3198.         GetMovieDuration( pMovieData->mMovie );
  3199.  
  3200.     // This routine queries qtw.ini for defaults
  3201.     PlayerGetDefaultOptions( &pMovieData->qtoleOptions );
  3202.  
  3203.     if( pMovieData->qtoleOptions.bSizeHalf ) {
  3204.         pMovieData->qtoleOptions.sizeCurrent.cx =
  3205.             pMovieData->qtoleOptions.sizeNormal.cx / 2;
  3206.         pMovieData->qtoleOptions.sizeCurrent.cy =
  3207.             pMovieData->qtoleOptions.sizeNormal.cy / 2;
  3208.     }
  3209.     else if( pMovieData->qtoleOptions.bSizeDouble ) {
  3210.         pMovieData->qtoleOptions.sizeCurrent.cx =
  3211.             pMovieData->qtoleOptions.sizeNormal.cx * 2;
  3212.         pMovieData->qtoleOptions.sizeCurrent.cy =
  3213.             pMovieData->qtoleOptions.sizeNormal.cy * 2;
  3214.     }
  3215.     else // Set to normal size if not half or double
  3216.     {
  3217.         pMovieData->qtoleOptions.sizeCurrent =
  3218.             pMovieData->qtoleOptions.sizeNormal;
  3219.     }
  3220.  
  3221.     lstrcpy( pMovieData->qtoleOptions.szCaption, pMovieData->szMovieName );
  3222.     lstrcat( pMovieData->qtoleOptions.szCaption, pMovieData->szMovieExt );
  3223.  
  3224.     return;
  3225. }
  3226.  
  3227.  
  3228. // Function: UpdateMovieForOptions - Sets movie options according to values
  3229. //                                   set in options dialog
  3230. // --------------------------------------------------------------------
  3231. // Parameters: HWND          hwndMovie;      Movie window handle
  3232. //             NPMOVIEDATA   pMovieData;     Movie data structure
  3233. //             BOOL          bCalledByOLE    TRUE if called by ole callback func.
  3234. //
  3235. // Returns:    None
  3236. // --------------------------------------------------------------------
  3237. VOID FAR UpdateMovieForOptions
  3238.     ( HWND hwndMovie, NPMOVIEDATA pMovieData, BOOL bCalledByOLE )
  3239.  
  3240. {
  3241.     TimeRecord   trTime;
  3242.  
  3243.     if( pMovieData->qtoleOptions.bLoop )
  3244.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_LOOP, 0L );
  3245.     else if( pMovieData->qtoleOptions.bLoopPalindrome )
  3246.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_BACKANDFORTH, 0L );
  3247.     else
  3248.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_STOPATEND, 0L );
  3249.  
  3250.     MCDoAction( pMovieData->mcMovieController,
  3251.         mcActionSetPlaySelection,
  3252.         (LPVOID) pMovieData->qtoleOptions.bPlaySelectionOnly );
  3253.  
  3254.     if( pMovieData->qtoleOptions.bSizeHalf )
  3255.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_HALFSIZE, 0L );
  3256.     else if( pMovieData->qtoleOptions.bSizeNormal )
  3257.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_NORMALSIZE, 0L );
  3258.     else if( pMovieData->qtoleOptions.bSizeDouble )
  3259.         SendMessage( hwndMovie, WM_COMMAND, PLAYER_MOVIE_DOUBLESIZE, 0L );
  3260.     else if( bCalledByOLE )
  3261.         ResizeMovieAndWindow( hwndMovie, TRUE, pMovieData,
  3262.         pMovieData->qtoleOptions.sizeCurrent.cx,
  3263.         pMovieData->qtoleOptions.sizeCurrent.cy );
  3264.  
  3265.     if( bCalledByOLE ) {
  3266.         trTime.value.dwHi = 0L;
  3267.         trTime.value.dwLo = pMovieData->qtoleOptions.tvDisplayFrame;
  3268.         trTime.scale = GetMovieTimeScale( pMovieData->mMovie );
  3269.         trTime.base  = TIMEBASE_DEFAULT;
  3270.  
  3271.         MCDoAction( pMovieData->mcMovieController,
  3272.             mcActionGoToTime, (LPVOID) &trTime );
  3273.  
  3274.         MCDoAction( pMovieData->mcMovieController,
  3275.             mcActionSetSelectionBegin,
  3276.             (LPVOID) &pMovieData->qtoleOptions.trSelStart );
  3277.         MCDoAction( pMovieData->mcMovieController,
  3278.             mcActionSetSelectionDuration,
  3279.             (LPVOID) &pMovieData->qtoleOptions.trSelDuration );
  3280.     }
  3281.  
  3282.     return;
  3283. }
  3284.  
  3285.  
  3286. // Function: PopulateOptionsStruct - Populates the options structure
  3287. // --------------------------------------------------------------------
  3288. // Parameters: HWND          hwndMovie      HWND of movie
  3289. //             NPMOVIEDATA   pMovieData     Movie data structure
  3290. //
  3291. // Returns:    None
  3292. // --------------------------------------------------------------------
  3293. static VOID NEAR PopulateOptionsStruct( HWND hwndMovie, NPMOVIEDATA pMovieData )
  3294.  
  3295. {
  3296.     BOOL           bLoop;           // Looping flag
  3297.     BOOL           bLoopPalindrome; // Loop palindrome flag
  3298.     RECT           rcMovie;         // Movie rectangle
  3299.     WORD           wMovieWidth;     // Movie width
  3300.     WORD           wMovieHeight;    // Movie height
  3301.     TimeRecord     trMovieTime;     // Movie time.. not used
  3302.  
  3303.  
  3304.     // Update these each time in case they get NULLed somewhere
  3305.     pMovieData->qtoleOptions.hwndObject = hwndMovie;
  3306.     pMovieData->qtoleOptions.mMovie     = pMovieData->mMovie;
  3307.  
  3308.     MCDoAction( pMovieData->mcMovieController,
  3309.         mcActionGetLooping, (LPVOID) &bLoop );
  3310.     MCDoAction( pMovieData->mcMovieController,
  3311.         mcActionGetLoopIsPalindrome, (LPVOID) &bLoopPalindrome );
  3312.  
  3313.     pMovieData->qtoleOptions.bLoop           = FALSE;
  3314.     pMovieData->qtoleOptions.bLoopPalindrome = FALSE;
  3315.     if( bLoop ) {
  3316.         if( bLoopPalindrome )
  3317.             pMovieData->qtoleOptions.bLoopPalindrome = TRUE;
  3318.         else
  3319.             pMovieData->qtoleOptions.bLoop = TRUE;
  3320.     }
  3321.  
  3322.     MCDoAction( pMovieData->mcMovieController,
  3323.         mcActionGetPlaySelection,
  3324.         (LPVOID) &pMovieData->qtoleOptions.bPlaySelectionOnly );
  3325.     if( pMovieData->qtoleOptions.bPlaySelectionOnly ) {
  3326.         pMovieData->qtoleOptions.trSelStart = pMovieData->trSelectionStart;
  3327.         pMovieData->qtoleOptions.trSelDuration =
  3328.             pMovieData->trSelectionDuration;
  3329.     }
  3330.     else {
  3331.         memset( &pMovieData->qtoleOptions.trSelStart,
  3332.             0, sizeof( TimeRecord ));
  3333.         memset( &pMovieData->qtoleOptions.trSelDuration,
  3334.             0, sizeof( TimeRecord ));
  3335.     }
  3336.  
  3337.     GetMovieBox( pMovieData->mMovie, &rcMovie );
  3338.     wMovieWidth  = rcMovie.right  - rcMovie.left;
  3339.     wMovieHeight = rcMovie.bottom - rcMovie.top;
  3340.  
  3341.     pMovieData->qtoleOptions.sizeCurrent.cx = wMovieWidth;
  3342.     pMovieData->qtoleOptions.sizeCurrent.cy = wMovieHeight;
  3343.  
  3344.     if( !pMovieData->qtoleOptions.bSoundOnlyMovie ) {
  3345.         if( !pMovieData->qtoleOptions.bCopyCurrentFrame ) {
  3346.             pMovieData->qtoleOptions.tvDisplayFrame =
  3347.                 GetMoviePosterTime( pMovieData->mMovie );
  3348.         }
  3349.         else {
  3350.             pMovieData->qtoleOptions.tvDisplayFrame =
  3351.                 GetMovieTime( pMovieData->mMovie, &trMovieTime );
  3352.         }
  3353.     }
  3354.     else {
  3355.         pMovieData->qtoleOptions.tvDisplayFrame = 0;
  3356.     }
  3357.  
  3358.     return;
  3359. }
  3360.  
  3361.  
  3362. //  This function is a query function called by other modules
  3363.  
  3364. // Function: PlayerQueryActiveMovieName - Query name of active movie
  3365. // --------------------------------------------------------------------
  3366. // Parameters: LPSTR      lpBuffer       string buffer
  3367. //
  3368. // Returns:    LPSTR      lpBuffer       Name of active movie
  3369. // --------------------------------------------------------------------
  3370. LPSTR FAR PlayerQueryActiveMovieName( LPSTR lpBuffer )
  3371.  
  3372. {
  3373.     HWND          hwndMovie;  // Handle to active window
  3374.     NPMOVIEDATA   pMovieData; // ->movie data struct
  3375.  
  3376.     hwndMovie = (HWND) SendMessage
  3377.         ( PlayerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  3378.     *lpBuffer = 0;
  3379.     if( pMovieData = (NPMOVIEDATA) GetWindowWord( hwndMovie, 0 ))
  3380.         lstrcpy( lpBuffer, pMovieData->szMovieName );
  3381.  
  3382.     return lpBuffer;
  3383. }
  3384.